lwp_t * cpu_switchto(lwp_t *oldlwp, lwp_t *newlwp, bool returning) { struct pcb *oldpcb = oldlwp ? lwp_getpcb(oldlwp) : NULL; struct pcb *newpcb = lwp_getpcb(newlwp); struct cpu_info *ci = curcpu(); cpu_softc_t *sc = device_private(ci->ci_dev); #ifdef CPU_DEBUG thunk_printf_debug("cpu_switchto [%s,pid=%d,lid=%d] -> [%s,pid=%d,lid=%d]\n", oldlwp ? oldlwp->l_name : "none", oldlwp ? oldlwp->l_proc->p_pid : -1, oldlwp ? oldlwp->l_lid : -1, newlwp ? newlwp->l_name : "none", newlwp ? newlwp->l_proc->p_pid : -1, newlwp ? newlwp->l_lid : -1); if (oldpcb) { thunk_printf_debug(" oldpcb uc_link=%p, uc_stack.ss_sp=%p, " "uc_stack.ss_size=%d\n", oldpcb->pcb_ucp.uc_link, oldpcb->pcb_ucp.uc_stack.ss_sp, (int)oldpcb->pcb_ucp.uc_stack.ss_size); } if (newpcb) { thunk_printf_debug(" newpcb uc_link=%p, uc_stack.ss_sp=%p, " "uc_stack.ss_size=%d\n", newpcb->pcb_ucp.uc_link, newpcb->pcb_ucp.uc_stack.ss_sp, (int)newpcb->pcb_ucp.uc_stack.ss_size); } #endif /* !CPU_DEBUG */ /* create atomic switcher */ thunk_makecontext(&sc->sc_ucp, (void (*)(void)) cpu_switchto_atomic, 2, oldlwp, newlwp, NULL, NULL); KASSERT(sc); if (oldpcb) { thunk_swapcontext(&oldpcb->pcb_ucp, &sc->sc_ucp); /* returns here */ } else { thunk_setcontext(&sc->sc_ucp); /* never returns */ } #ifdef CPU_DEBUG thunk_printf_debug("cpu_switchto: returning %p (was %p)\n", ci->ci_stash, oldlwp); #endif return ci->ci_stash; }
void cpu_lwp_free(struct lwp *l, int proc) { #ifdef CPU_DEBUG thunk_printf_debug("cpu_lwp_free (dummy)\n"); #endif }
void cpu_dumpconf(void) { #ifdef CPU_DEBUG thunk_printf_debug("cpu_dumpconf\n"); #endif }
int cpu_setmcontext(struct lwp *l, const mcontext_t *mcp, unsigned int flags) { struct pcb *pcb = lwp_getpcb(l); ucontext_t *ucp = &pcb->pcb_userret_ucp; #ifdef CPU_DEBUG thunk_printf_debug("cpu_setmcontext\n"); #endif memcpy(&ucp->uc_mcontext, mcp, sizeof(mcontext_t)); return 0; }
static void cpu_lwp_trampoline(ucontext_t *ucp, void (*func)(void *), void *arg) { #ifdef CPU_DEBUG thunk_printf_debug("cpu_lwp_trampoline called with func %p, arg %p\n", (void *) func, arg); #endif /* init lwp */ lwp_startup(curcpu()->ci_stash, curlwp); /* actual jump */ thunk_makecontext(ucp, (void (*)(void)) func, 1, arg, NULL, NULL, NULL); thunk_setcontext(ucp); }
void cpu_lwp_free2(struct lwp *l) { struct pcb *pcb = lwp_getpcb(l); #ifdef CPU_DEBUG thunk_printf_debug("cpu_lwp_free2\n"); #endif if (pcb == NULL) return; /* XXX nothing to do? */ }
void cpu_lwp_fork(struct lwp *l1, struct lwp *l2, void *stack, size_t stacksize, void (*func)(void *), void *arg) { struct pcb *pcb1 = lwp_getpcb(l1); struct pcb *pcb2 = lwp_getpcb(l2); #ifdef CPU_DEBUG thunk_printf_debug("cpu_lwp_fork [%s/%p] -> [%s/%p] stack=%p stacksize=%d\n", l1 ? l1->l_name : "none", l1, l2 ? l2->l_name : "none", l2, stack, (int)stacksize); #endif if (stack) panic("%s: stack passed, can't handle\n", __func__); /* copy the PCB and its switchframes from parent */ memcpy(pcb2, pcb1, sizeof(struct pcb)); /* refresh context */ if (thunk_getcontext(&pcb2->pcb_ucp)) panic("getcontext failed"); /* recalculate the system stack top */ pcb2->sys_stack_top = pcb2->sys_stack + TRAPSTACKSIZE; /* get l2 its own stack */ pcb2->pcb_ucp.uc_stack.ss_sp = pcb2->sys_stack; pcb2->pcb_ucp.uc_stack.ss_size = pcb2->sys_stack_top - pcb2->sys_stack; pcb2->pcb_ucp.uc_link = &pcb2->pcb_userret_ucp; thunk_sigemptyset(&pcb2->pcb_ucp.uc_sigmask); pcb2->pcb_ucp.uc_flags = _UC_STACK | _UC_CPU | _UC_SIGMASK; thunk_makecontext(&pcb2->pcb_ucp, (void (*)(void)) cpu_lwp_trampoline, 3, &pcb2->pcb_ucp, func, arg, NULL); }
void syscall(void) { lwp_t *l = curlwp; const struct proc * const p = l->l_proc; const struct sysent *callp; struct pcb *pcb = lwp_getpcb(l); ucontext_t *ucp = &pcb->pcb_userret_ucp; register_t copyargs[2+SYS_MAXSYSARGS]; register_t *args; register_t rval[2]; uint32_t code, opcode; uint nargs, argsize; int error; /* system call accounting */ curcpu()->ci_data.cpu_nsyscall++; LWP_CACHE_CREDS(l, l->l_proc); /* XXX do we want do do emulation? */ md_syscall_get_opcode(ucp, &opcode); md_syscall_get_syscallnumber(ucp, &code); code &= (SYS_NSYSENT -1); callp = p->p_emul->e_sysent + code; nargs = callp->sy_narg; argsize = callp->sy_argsize; args = copyargs; rval[0] = rval[1] = 0; error = md_syscall_getargs(l, ucp, nargs, argsize, args); #if 0 aprint_debug("syscall no. %d, ", code); aprint_debug("nargs %d, argsize %d => ", nargs, argsize); thunk_printf_debug("syscall no. %d, ", code); thunk_printf_debug("nargs %d, argsize %d => ", nargs, argsize); #endif /* * TODO change the pre and post printing into functions so they can be * easily adjusted and dont clobber up this space */ if (!error) syscall_args_print(l, code, nargs, argsize, args); md_syscall_inc_pc(ucp, opcode); if (!error) { error = sy_invoke(callp, l, args, rval, code); } syscall_retvals_print(l, curlwp, code, nargs, args, error, rval); //out: switch (error) { default: /* fall trough */ case 0: md_syscall_set_returnargs(l, ucp, error, rval); /* fall trough */ case EJUSTRETURN: break; case ERESTART: md_syscall_dec_pc(ucp, opcode); /* nothing to do */ break; } //thunk_printf_debug("end of syscall : return to userland\n"); //if (code != 4) thunk_printf("userret() code %d\n", code); }