📄 process.c
字号:
break; case SIGTRAP: relay_signal(SIGTRAP, regs); break; case SIGIO: case SIGVTALRM: case SIGILL: case SIGBUS: case SIGFPE: case SIGWINCH: user_signal(WSTOPSIG(status), regs, pid); break; default: printk("userspace - child stopped with signal " "%d\n", WSTOPSIG(status)); } pid = userspace_pid[0]; interrupt_end(); /* Avoid -ERESTARTSYS handling in host */ PT_SYSCALL_NR(regs->skas.regs) = -1; } }}#define INIT_JMP_NEW_THREAD 0#define INIT_JMP_REMOVE_SIGSTACK 1#define INIT_JMP_CALLBACK 2#define INIT_JMP_HALT 3#define INIT_JMP_REBOOT 4int copy_context_skas0(unsigned long new_stack, int pid){ int err; unsigned long regs[MAX_REG_NR]; 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; __u64 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) { { 0, 1000000 / hz() }, { 0, 1000000 / hz() }})}); get_safe_registers(regs); /* Set parent's instruction pointer to start of clone-stub */ regs[REGS_IP_INDEX] = UML_CONFIG_STUB_CODE + (unsigned long) stub_clone_handler - (unsigned long) &__syscall_stub_start; regs[REGS_SP_INDEX] = UML_CONFIG_STUB_DATA + PAGE_SIZE - sizeof(void *); err = ptrace_setregs(pid, regs); if(err < 0) panic("copy_context_skas0 : PTRACE_SETREGS failed, " "pid = %d, errno = %d\n", pid, errno); /* 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. */ wait_stub_done(pid, 0, "copy_context_skas0"); 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, -1, "copy_context_skas0"); if (child_data->err != UML_CONFIG_STUB_DATA) panic("copy_context_skas0 - stub-child reports error %d\n", child_data->err); if (ptrace(PTRACE_OLDSETOPTIONS, pid, NULL, (void *)PTRACE_O_TRACESYSGOOD) < 0) panic("copy_context_skas0 : PTRACE_SETOPTIONS failed, " "errno = %d\n", errno); return pid;}/* * 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){ struct proc_mm_op mmop; int n; mmop = ((struct proc_mm_op) { .op = MM_MMAP, .u = { .mmap = { .addr = code, .len = PAGE_SIZE, .prot = PROT_EXEC, .flags = MAP_FIXED | MAP_PRIVATE, .fd = stub_code_fd, .offset = stub_code_offset } } }); n = os_write_file(fd, &mmop, sizeof(mmop)); if(n != sizeof(mmop)) panic("map_stub_pages : /proc/mm map for code failed, " "err = %d\n", -n); if ( stack ) { __u64 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 = PAGE_SIZE, .prot = PROT_READ | PROT_WRITE, .flags = MAP_FIXED | MAP_SHARED, .fd = map_fd, .offset = map_offset } } }); n = os_write_file(fd, &mmop, sizeof(mmop)); if(n != sizeof(mmop)) panic("map_stub_pages : /proc/mm map for data failed, " "err = %d\n", -n); }}void new_thread(void *stack, void **switch_buf_ptr, void **fork_buf_ptr, void (*handler)(int)){ unsigned long flags; sigjmp_buf switch_buf, fork_buf; *switch_buf_ptr = &switch_buf; *fork_buf_ptr = &fork_buf; /* Somewhat subtle - siglongjmp restores the signal mask before doing * the longjmp. This means that when jumping from one stack to another * when the target stack has interrupts enabled, an interrupt may occur * on the source stack. This is bad when starting up a process because * it's not supposed to get timer ticks until it has been scheduled. * So, we disable interrupts around the sigsetjmp to ensure that * they can't happen until we get back here where they are safe. */ flags = get_signals(); block_signals(); if(sigsetjmp(fork_buf, 1) == 0) new_thread_proc(stack, handler); remove_sigstack(); set_signals(flags);}void thread_wait(void *sw, void *fb){ sigjmp_buf buf, **switch_buf = sw, *fork_buf; *switch_buf = &buf; fork_buf = fb; if(sigsetjmp(buf, 1) == 0) siglongjmp(*fork_buf, INIT_JMP_REMOVE_SIGSTACK);}void switch_threads(void *me, void *next){ sigjmp_buf my_buf, **me_ptr = me, *next_buf = next; *me_ptr = &my_buf; if(sigsetjmp(my_buf, 1) == 0) siglongjmp(*next_buf, 1);}static sigjmp_buf initial_jmpbuf;/* XXX Make these percpu */static void (*cb_proc)(void *arg);static void *cb_arg;static sigjmp_buf *cb_back;int start_idle_thread(void *stack, void *switch_buf_ptr, void **fork_buf_ptr){ sigjmp_buf **switch_buf = switch_buf_ptr; int n; set_handler(SIGWINCH, (__sighandler_t) sig_handler, SA_ONSTACK | SA_RESTART, SIGUSR1, SIGIO, SIGALRM, SIGVTALRM, -1); *fork_buf_ptr = &initial_jmpbuf; n = sigsetjmp(initial_jmpbuf, 1); switch(n){ case INIT_JMP_NEW_THREAD: new_thread_proc((void *) stack, new_thread_handler); break; case INIT_JMP_REMOVE_SIGSTACK: remove_sigstack(); break; case INIT_JMP_CALLBACK: (*cb_proc)(cb_arg); siglongjmp(*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); } 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; cb_proc = proc; cb_arg = arg; cb_back = &here; block_signals(); if(sigsetjmp(here, 1) == 0) siglongjmp(initial_jmpbuf, INIT_JMP_CALLBACK); unblock_signals(); cb_proc = NULL; cb_arg = NULL; cb_back = NULL;}void halt_skas(void){ block_signals(); siglongjmp(initial_jmpbuf, INIT_JMP_HALT);}void reboot_skas(void){ block_signals(); siglongjmp(initial_jmpbuf, INIT_JMP_REBOOT);}void switch_mm_skas(struct mm_id *mm_idp){ int err;#warning need cpu pid in switch_mm_skas if(proc_mm){ err = ptrace(PTRACE_SWITCH_MM, userspace_pid[0], 0, mm_idp->u.mm_fd); if(err) panic("switch_mm_skas - PTRACE_SWITCH_MM failed, " "errno = %d\n", errno); } else userspace_pid[0] = mm_idp->u.pid;}/* * 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: */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -