📄 process.c
字号:
err = ptrace(op, pid, 0, 0); if (err) panic("userspace - could not resume userspace process, " "pid=%d, ptrace operation = %d, errno = %d\n", pid, op, errno); CATCH_EINTR(err = waitpid(pid, &status, WUNTRACED | __WALL)); if (err < 0) panic("userspace - waitpid failed, errno = %d\n", errno); regs->is_user = 1; save_registers(pid, regs); UPT_SYSCALL_NR(regs) = -1; /* Assume: It's not a syscall */ if (WIFSTOPPED(status)) { int sig = WSTOPSIG(status); switch(sig) { case SIGSEGV: if (PTRACE_FULL_FAULTINFO || !ptrace_faultinfo) { get_skas_faultinfo(pid, ®s->faultinfo); (*sig_info[SIGSEGV])(SIGSEGV, regs); } else handle_segv(pid, regs); break; case SIGTRAP + 0x80: handle_trap(pid, regs, local_using_sysemu); break; case SIGTRAP: relay_signal(SIGTRAP, regs); break; case SIGVTALRM: now = os_nsecs(); if(now < nsecs) break; block_signals(); (*sig_info[sig])(sig, regs); unblock_signals(); nsecs = timer.it_value.tv_sec * UM_NSEC_PER_SEC + timer.it_value.tv_usec * UM_NSEC_PER_USEC; nsecs += os_nsecs(); break; case SIGIO: case SIGILL: case SIGBUS: case SIGFPE: case SIGWINCH: block_signals(); (*sig_info[sig])(sig, regs); unblock_signals(); break; default: printk(UM_KERN_ERR "userspace - child stopped " "with signal %d\n", sig); } pid = userspace_pid[0]; interrupt_end(); /* Avoid -ERESTARTSYS handling in host */ if (PT_SYSCALL_NR_OFFSET != PT_SYSCALL_RET_OFFSET) PT_SYSCALL_NR(regs->gp) = -1; } }}static unsigned long thread_regs[MAX_REG_NR];static int __init init_thread_regs(void){ get_safe_registers(thread_regs); /* Set parent's instruction pointer to start of clone-stub */ thread_regs[REGS_IP_INDEX] = STUB_CODE + (unsigned long) stub_clone_handler - (unsigned long) &__syscall_stub_start; thread_regs[REGS_SP_INDEX] = STUB_DATA + UM_KERN_PAGE_SIZE - sizeof(void *);#ifdef __SIGNAL_FRAMESIZE thread_regs[REGS_SP_INDEX] -= __SIGNAL_FRAMESIZE;#endif return 0;}__initcall(init_thread_regs);int copy_context_skas0(unsigned long new_stack, int pid){ struct timeval tv = { .tv_sec = 0, .tv_usec = UM_USEC_PER_SEC / UM_HZ }; int err; unsigned long current_stack = current_stub_stack(); struct stub_data *data = (struct stub_data *) current_stack; struct stub_data *child_data = (struct stub_data *) new_stack; unsigned long long new_offset; int new_fd = phys_mapping(to_phys((void *)new_stack), &new_offset); /* * prepare offset and fd of child's stack as argument for parent's * and child's mmap2 calls */ *data = ((struct stub_data) { .offset = MMAP_OFFSET(new_offset), .fd = new_fd, .timer = ((struct itimerval) { .it_value = tv, .it_interval = tv }) }); err = ptrace_setregs(pid, thread_regs); if (err < 0) panic("copy_context_skas0 : PTRACE_SETREGS failed, " "pid = %d, errno = %d\n", pid, -err); /* set a well known return code for detection of child write failure */ child_data->err = 12345678; /* * Wait, until parent has finished its work: read child's pid from * parent's stack, and check, if bad result. */ err = ptrace(PTRACE_CONT, pid, 0, 0); if (err) panic("Failed to continue new process, pid = %d, " "errno = %d\n", pid, errno); wait_stub_done(pid); pid = data->err; if (pid < 0) panic("copy_context_skas0 - stub-parent reports error %d\n", -pid); /* * Wait, until child has finished too: read child's result from * child's stack and check it. */ wait_stub_done(pid); if (child_data->err != STUB_DATA) panic("copy_context_skas0 - stub-child reports error %ld\n", child_data->err); if (ptrace(PTRACE_OLDSETOPTIONS, pid, NULL, (void *)PTRACE_O_TRACESYSGOOD) < 0) panic("copy_context_skas0 : PTRACE_OLDSETOPTIONS failed, " "errno = %d\n", errno); return pid;}/* * This is used only, if stub pages are needed, while proc_mm is * available. 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){ struct proc_mm_op mmop; int n; unsigned long long code_offset; int code_fd = phys_mapping(to_phys((void *) &__syscall_stub_start), &code_offset); mmop = ((struct proc_mm_op) { .op = MM_MMAP, .u = { .mmap = { .addr = code, .len = UM_KERN_PAGE_SIZE, .prot = PROT_EXEC, .flags = MAP_FIXED | MAP_PRIVATE, .fd = code_fd, .offset = code_offset } } }); CATCH_EINTR(n = write(fd, &mmop, sizeof(mmop))); if (n != sizeof(mmop)) { n = errno; printk(UM_KERN_ERR "mmap args - addr = 0x%lx, fd = %d, " "offset = %llx\n", code, code_fd, (unsigned long long) code_offset); panic("map_stub_pages : /proc/mm map for code failed, " "err = %d\n", n); } if (stack) { unsigned long long map_offset; int map_fd = phys_mapping(to_phys((void *)stack), &map_offset); mmop = ((struct proc_mm_op) { .op = MM_MMAP, .u = { .mmap = { .addr = data, .len = UM_KERN_PAGE_SIZE, .prot = PROT_READ | PROT_WRITE, .flags = MAP_FIXED | MAP_SHARED, .fd = map_fd, .offset = map_offset } } }); CATCH_EINTR(n = write(fd, &mmop, sizeof(mmop))); if (n != sizeof(mmop)) panic("map_stub_pages : /proc/mm map for data failed, " "err = %d\n", errno); }}void new_thread(void *stack, jmp_buf *buf, void (*handler)(void)){ (*buf)[0].JB_IP = (unsigned long) handler; (*buf)[0].JB_SP = (unsigned long) stack + UM_THREAD_SIZE - sizeof(void *);}#define INIT_JMP_NEW_THREAD 0#define INIT_JMP_CALLBACK 1#define INIT_JMP_HALT 2#define INIT_JMP_REBOOT 3void switch_threads(jmp_buf *me, jmp_buf *you){ if (UML_SETJMP(me) == 0) UML_LONGJMP(you, 1);}static jmp_buf initial_jmpbuf;/* XXX Make these percpu */static void (*cb_proc)(void *arg);static void *cb_arg;static jmp_buf *cb_back;int start_idle_thread(void *stack, jmp_buf *switch_buf){ int n; set_handler(SIGWINCH, (__sighandler_t) sig_handler, SA_ONSTACK | SA_RESTART, SIGUSR1, SIGIO, SIGVTALRM, -1); /* * Can't use UML_SETJMP or UML_LONGJMP here because they save * and restore signals, with the possible side-effect of * trying to handle any signals which came when they were * blocked, which can't be done on this stack. * Signals must be blocked when jumping back here and restored * after returning to the jumper. */ n = setjmp(initial_jmpbuf); switch(n) { case INIT_JMP_NEW_THREAD: (*switch_buf)[0].JB_IP = (unsigned long) new_thread_handler; (*switch_buf)[0].JB_SP = (unsigned long) stack + UM_THREAD_SIZE - sizeof(void *); break; case INIT_JMP_CALLBACK: (*cb_proc)(cb_arg); longjmp(*cb_back, 1); break; case INIT_JMP_HALT: kmalloc_ok = 0; return 0; case INIT_JMP_REBOOT: kmalloc_ok = 0; return 1; default: panic("Bad sigsetjmp return in start_idle_thread - %d\n", n); } longjmp(*switch_buf, 1);}void initial_thread_cb_skas(void (*proc)(void *), void *arg){ jmp_buf here; cb_proc = proc; cb_arg = arg; cb_back = &here; block_signals(); if (UML_SETJMP(&here) == 0) UML_LONGJMP(&initial_jmpbuf, INIT_JMP_CALLBACK); unblock_signals(); cb_proc = NULL; cb_arg = NULL; cb_back = NULL;}void halt_skas(void){ block_signals(); UML_LONGJMP(&initial_jmpbuf, INIT_JMP_HALT);}void reboot_skas(void){ block_signals(); UML_LONGJMP(&initial_jmpbuf, INIT_JMP_REBOOT);}void __switch_mm(struct mm_id *mm_idp){ int err; /* FIXME: need cpu pid in __switch_mm */ if (proc_mm) { err = ptrace(PTRACE_SWITCH_MM, userspace_pid[0], 0, mm_idp->u.mm_fd); if (err) panic("__switch_mm - PTRACE_SWITCH_MM failed, " "errno = %d\n", errno); } else userspace_pid[0] = mm_idp->u.pid;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -