void cpu_lwp_free(struct lwp *l, int proc) { /* Flush the LWP out of the FPU. */ hppa_fpu_flush(l); }
void cpu_swapout(struct lwp *l) { /* Flush this LWP out of the FPU. */ hppa_fpu_flush(l); }
int process_write_fpregs(struct lwp *l, const struct fpreg *fpregs) { hppa_fpu_flush(l); bcopy(fpregs, l->l_addr->u_pcb.pcb_fpregs, sizeof(*fpregs)); fdcache(HPPA_SID_KERNEL, (vaddr_t)&l->l_addr->u_pcb.pcb_fpregs, sizeof(*fpregs)); return 0; }
void cpu_lwp_free(struct lwp *l, int proc) { struct pcb *pcb = lwp_getpcb(l); /* * If this thread was using the FPU, disable the FPU and record * that it's unused. */ hppa_fpu_flush(l); pool_put(&hppa_fppl, pcb->pcb_fpregs); }
void cpu_getmcontext(struct lwp *l, mcontext_t *mcp, unsigned int *flags) { struct trapframe *tf = l->l_md.md_regs; struct pcb *pcb = lwp_getpcb(l); __greg_t *gr = mcp->__gregs; __greg_t ras_pc; gr[0] = tf->tf_ipsw; gr[1] = tf->tf_r1; gr[2] = tf->tf_rp; gr[3] = tf->tf_r3; gr[4] = tf->tf_r4; gr[5] = tf->tf_r5; gr[6] = tf->tf_r6; gr[7] = tf->tf_r7; gr[8] = tf->tf_r8; gr[9] = tf->tf_r9; gr[10] = tf->tf_r10; gr[11] = tf->tf_r11; gr[12] = tf->tf_r12; gr[13] = tf->tf_r13; gr[14] = tf->tf_r14; gr[15] = tf->tf_r15; gr[16] = tf->tf_r16; gr[17] = tf->tf_r17; gr[18] = tf->tf_r18; gr[19] = tf->tf_t4; gr[20] = tf->tf_t3; gr[21] = tf->tf_t2; gr[22] = tf->tf_t1; gr[23] = tf->tf_arg3; gr[24] = tf->tf_arg2; gr[25] = tf->tf_arg1; gr[26] = tf->tf_arg0; gr[27] = tf->tf_dp; gr[28] = tf->tf_ret0; gr[29] = tf->tf_ret1; gr[30] = tf->tf_sp; gr[31] = tf->tf_r31; gr[_REG_SAR] = tf->tf_sar; gr[_REG_PCSQH] = tf->tf_iisq_head; gr[_REG_PCSQT] = tf->tf_iisq_tail; gr[_REG_PCOQH] = tf->tf_iioq_head; gr[_REG_PCOQT] = tf->tf_iioq_tail; gr[_REG_SR0] = tf->tf_sr0; gr[_REG_SR1] = tf->tf_sr1; gr[_REG_SR2] = tf->tf_sr2; gr[_REG_SR3] = tf->tf_sr3; gr[_REG_SR4] = tf->tf_sr4; gr[_REG_CR27] = tf->tf_cr27; #if 0 gr[_REG_CR26] = tf->tf_cr26; #endif ras_pc = (__greg_t)ras_lookup(l->l_proc, (void *)(gr[_REG_PCOQH] & ~HPPA_PC_PRIV_MASK)); if (ras_pc != -1) { ras_pc |= HPPA_PC_PRIV_USER; gr[_REG_PCOQH] = ras_pc; gr[_REG_PCOQT] = ras_pc + 4; } *flags |= _UC_CPU | _UC_TLSBASE; if (l->l_md.md_flags & 0) { return; } hppa_fpu_flush(l); memcpy(&mcp->__fpregs, pcb->pcb_fpregs, sizeof(mcp->__fpregs)); *flags |= _UC_FPU; }
int cpu_setmcontext(struct lwp *l, const mcontext_t *mcp, unsigned int flags) { struct trapframe *tf = l->l_md.md_regs; struct proc *p = l->l_proc; struct pmap *pmap = p->p_vmspace->vm_map.pmap; const __greg_t *gr = mcp->__gregs; int error; if ((flags & _UC_CPU) != 0) { error = cpu_mcontext_validate(l, mcp); if (error) return error; tf->tf_ipsw = gr[0] | (hppa_cpu_ispa20_p() ? PSW_O : 0); tf->tf_r1 = gr[1]; tf->tf_rp = gr[2]; tf->tf_r3 = gr[3]; tf->tf_r4 = gr[4]; tf->tf_r5 = gr[5]; tf->tf_r6 = gr[6]; tf->tf_r7 = gr[7]; tf->tf_r8 = gr[8]; tf->tf_r9 = gr[9]; tf->tf_r10 = gr[10]; tf->tf_r11 = gr[11]; tf->tf_r12 = gr[12]; tf->tf_r13 = gr[13]; tf->tf_r14 = gr[14]; tf->tf_r15 = gr[15]; tf->tf_r16 = gr[16]; tf->tf_r17 = gr[17]; tf->tf_r18 = gr[18]; tf->tf_t4 = gr[19]; tf->tf_t3 = gr[20]; tf->tf_t2 = gr[21]; tf->tf_t1 = gr[22]; tf->tf_arg3 = gr[23]; tf->tf_arg2 = gr[24]; tf->tf_arg1 = gr[25]; tf->tf_arg0 = gr[26]; tf->tf_dp = gr[27]; tf->tf_ret0 = gr[28]; tf->tf_ret1 = gr[29]; tf->tf_sp = gr[30]; tf->tf_r31 = gr[31]; tf->tf_sar = gr[_REG_SAR]; tf->tf_iisq_head = pmap_sid(pmap, gr[_REG_PCOQH]); tf->tf_iisq_tail = pmap_sid(pmap, gr[_REG_PCOQT]); tf->tf_iioq_head = gr[_REG_PCOQH]; tf->tf_iioq_tail = gr[_REG_PCOQT]; if (tf->tf_iioq_head >= 0xc0000020) { tf->tf_iioq_head &= ~HPPA_PC_PRIV_MASK; } else { tf->tf_iioq_head |= HPPA_PC_PRIV_USER; } if (tf->tf_iioq_tail >= 0xc0000020) { tf->tf_iioq_tail &= ~HPPA_PC_PRIV_MASK; } else { tf->tf_iioq_tail |= HPPA_PC_PRIV_USER; } #if 0 tf->tf_sr0 = gr[_REG_SR0]; tf->tf_sr1 = gr[_REG_SR1]; tf->tf_sr2 = gr[_REG_SR2]; tf->tf_sr3 = gr[_REG_SR3]; tf->tf_sr4 = gr[_REG_SR4]; tf->tf_cr26 = gr[_REG_CR26]; #endif } /* Restore the private thread context */ if (flags & _UC_TLSBASE) { lwp_setprivate(l, (void *)(uintptr_t)gr[_REG_CR27]); tf->tf_cr27 = gr[_REG_CR27]; } /* Restore the floating point registers */ if ((flags & _UC_FPU) != 0) { struct pcb *pcb = lwp_getpcb(l); hppa_fpu_flush(l); memcpy(pcb->pcb_fpregs, &mcp->__fpregs, sizeof(mcp->__fpregs)); } mutex_enter(p->p_lock); if (flags & _UC_SETSTACK) l->l_sigstk.ss_flags |= SS_ONSTACK; if (flags & _UC_CLRSTACK) l->l_sigstk.ss_flags &= ~SS_ONSTACK; mutex_exit(p->p_lock); return 0; }
void cpu_lwp_fork(struct lwp *l1, struct lwp *l2, void *stack, size_t stacksize, void (*func)(void *), void *arg) { struct pcb *pcb1, *pcb2; struct trapframe *tf; register_t sp, osp; vaddr_t uv; KASSERT(round_page(sizeof(struct pcb)) <= PAGE_SIZE); pcb1 = lwp_getpcb(l1); pcb2 = lwp_getpcb(l2); l2->l_md.md_astpending = 0; l2->l_md.md_flags = 0; /* Flush the parent LWP out of the FPU. */ hppa_fpu_flush(l1); /* Now copy the parent PCB into the child. */ memcpy(pcb2, pcb1, sizeof(struct pcb)); pcb2->pcb_fpregs = pool_get(&hppa_fppl, PR_WAITOK); *pcb2->pcb_fpregs = *pcb1->pcb_fpregs; /* reset any of the pending FPU exceptions from parent */ pcb2->pcb_fpregs->fpr_regs[0] = HPPA_FPU_FORK(pcb2->pcb_fpregs->fpr_regs[0]); pcb2->pcb_fpregs->fpr_regs[1] = 0; pcb2->pcb_fpregs->fpr_regs[2] = 0; pcb2->pcb_fpregs->fpr_regs[3] = 0; l2->l_md.md_bpva = l1->l_md.md_bpva; l2->l_md.md_bpsave[0] = l1->l_md.md_bpsave[0]; l2->l_md.md_bpsave[1] = l1->l_md.md_bpsave[1]; uv = uvm_lwp_getuarea(l2); sp = (register_t)uv + PAGE_SIZE; l2->l_md.md_regs = tf = (struct trapframe *)sp; sp += sizeof(struct trapframe); /* copy the l1's trapframe to l2 */ memcpy(tf, l1->l_md.md_regs, sizeof(*tf)); /* Fill out all the PAs we are going to need in locore. */ cpu_activate_pcb(l2); if (__predict_true(l2->l_proc->p_vmspace != NULL)) { struct proc *p = l2->l_proc; pmap_t pmap = p->p_vmspace->vm_map.pmap; pa_space_t space = pmap->pm_space; /* Load all of the user's space registers. */ tf->tf_sr0 = tf->tf_sr1 = tf->tf_sr3 = tf->tf_sr2 = tf->tf_sr4 = tf->tf_sr5 = tf->tf_sr6 = space; tf->tf_iisq_head = tf->tf_iisq_tail = space; /* Load the protection registers */ tf->tf_pidr1 = tf->tf_pidr2 = pmap->pm_pid; /* * theoretically these could be inherited from the father, * but just in case. */ tf->tf_sr7 = HPPA_SID_KERNEL; mfctl(CR_EIEM, tf->tf_eiem); tf->tf_ipsw = PSW_C | PSW_Q | PSW_P | PSW_D | PSW_I /* | PSW_L */ | (curcpu()->ci_psw & PSW_O); } /* * Set up return value registers as libc:fork() expects */ tf->tf_ret0 = l1->l_proc->p_pid; tf->tf_ret1 = 1; /* ischild */ tf->tf_t1 = 0; /* errno */ /* * If specified, give the child a different stack. */ if (stack != NULL) tf->tf_sp = (register_t)stack; /* * Build stack frames for the cpu_switchto & co. */ osp = sp; /* lwp_trampoline's frame */ sp += HPPA_FRAME_SIZE; *(register_t *)(sp) = 0; /* previous frame pointer */ *(register_t *)(sp + HPPA_FRAME_PSP) = osp; *(register_t *)(sp + HPPA_FRAME_CRP) = (register_t)lwp_trampoline; *HPPA_FRAME_CARG(2, sp) = KERNMODE(func); *HPPA_FRAME_CARG(3, sp) = (register_t)arg; /* * cpu_switchto's frame * stack usage is std frame + callee-save registers */ sp += HPPA_FRAME_SIZE + 16*4; pcb2->pcb_ksp = sp; fdcache(HPPA_SID_KERNEL, uv, sp - uv); }
void cpu_lwp_fork(struct lwp *l1, struct lwp *l2, void *stack, size_t stacksize, void (*func)(void *), void *arg) { struct pcb *pcbp; struct trapframe *tf; register_t sp, osp; #ifdef DIAGNOSTIC if (round_page(sizeof(struct user)) > PAGE_SIZE) panic("USPACE too small for user"); #endif /* Flush the parent process out of the FPU. */ hppa_fpu_flush(l1); /* Now copy the parent PCB into the child. */ pcbp = &l2->l_addr->u_pcb; bcopy(&l1->l_addr->u_pcb, pcbp, sizeof(*pcbp)); sp = (register_t)l2->l_addr + PAGE_SIZE; l2->l_md.md_regs = tf = (struct trapframe *)sp; sp += sizeof(struct trapframe); bcopy(l1->l_md.md_regs, tf, sizeof(*tf)); /* * cpu_swapin() is supposed to fill out all the PAs * we gonna need in locore */ cpu_swapin(l2); /* Activate this process' pmap. */ pmap_activate(l2); /* * theoretically these could be inherited from the father, * but just in case. */ tf->tf_sr7 = HPPA_SID_KERNEL; mfctl(CR_EIEM, tf->tf_eiem); tf->tf_ipsw = PSW_C | PSW_Q | PSW_P | PSW_D | PSW_I /* | PSW_L */; pcbp->pcb_fpregs[HPPA_NFPREGS] = 0; /* * Set up return value registers as libc:fork() expects */ tf->tf_ret0 = l1->l_proc->p_pid; tf->tf_ret1 = 1; /* ischild */ tf->tf_t1 = 0; /* errno */ /* * If specified, give the child a different stack. */ if (stack != NULL) tf->tf_sp = (register_t)stack; /* * Build a stack frame for the cpu_switch & co. */ osp = sp; sp += HPPA_FRAME_SIZE + 16*4; /* std frame + calee-save registers */ *HPPA_FRAME_CARG(0, sp) = tf->tf_sp; *HPPA_FRAME_CARG(1, sp) = KERNMODE(func); *HPPA_FRAME_CARG(2, sp) = (register_t)arg; *(register_t*)(sp + HPPA_FRAME_PSP) = osp; *(register_t*)(sp + HPPA_FRAME_CRP) = (register_t)switch_trampoline; tf->tf_sp = sp; fdcache(HPPA_SID_KERNEL, (vaddr_t)l2->l_addr, sp - (vaddr_t)l2->l_addr); }