static void user_backtrace_raw(u_int pc, u_int fp) { int frame_number; int arg_number; for (frame_number = 0; frame_number < 100 && pc > HPPA_PC_PRIV_MASK && fp; frame_number++) { printf("%3d: pc=%08x%s fp=0x%08x", frame_number, pc & ~HPPA_PC_PRIV_MASK, USERMODE(pc) ? "" : "**", fp); for(arg_number = 0; arg_number < 4; arg_number++) printf(" arg%d=0x%08x", arg_number, (int) fuword(HPPA_FRAME_CARG(arg_number, fp))); printf("\n"); pc = fuword(((register_t *) fp) - 5); /* fetch rp */ if (pc == -1) { printf(" fuword for pc failed\n"); break; } fp = fuword(((register_t *) fp) + 0); /* fetch previous fp */ if (fp == -1) { printf(" fuword for fp failed\n"); break; } } printf(" backtrace stopped with pc %08x fp 0x%08x\n", pc, fp); }
void cpu_fork(struct proc *p1, struct proc *p2, 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)) > NBPG) panic("USPACE too small for user"); #endif fpu_proc_save(p1); pcbp = &p2->p_addr->u_pcb; bcopy(&p1->p_addr->u_pcb, pcbp, sizeof(*pcbp)); /* space is cached for the copy{in,out}'s pleasure */ pcbp->pcb_space = p2->p_vmspace->vm_map.pmap->pm_space; pcbp->pcb_fpstate = pool_get(&hppa_fppl, PR_WAITOK); *pcbp->pcb_fpstate = *p1->p_addr->u_pcb.pcb_fpstate; /* reset any of the pending FPU exceptions from parent */ pcbp->pcb_fpstate->hfp_regs.fpr_regs[0] = HPPA_FPU_FORK(pcbp->pcb_fpstate->hfp_regs.fpr_regs[0]); pcbp->pcb_fpstate->hfp_regs.fpr_regs[1] = 0; pcbp->pcb_fpstate->hfp_regs.fpr_regs[2] = 0; pcbp->pcb_fpstate->hfp_regs.fpr_regs[3] = 0; p2->p_md.md_bpva = p1->p_md.md_bpva; p2->p_md.md_bpsave[0] = p1->p_md.md_bpsave[0]; p2->p_md.md_bpsave[1] = p1->p_md.md_bpsave[1]; sp = (register_t)p2->p_addr + NBPG; p2->p_md.md_regs = tf = (struct trapframe *)sp; sp += sizeof(struct trapframe); bcopy(p1->p_md.md_regs, tf, sizeof(*tf)); tf->tf_cr30 = (paddr_t)pcbp->pcb_fpstate; tf->tf_sr0 = tf->tf_sr1 = tf->tf_sr2 = tf->tf_sr3 = tf->tf_sr4 = tf->tf_sr5 = tf->tf_sr6 = tf->tf_iisq_head = tf->tf_iisq_tail = p2->p_vmspace->vm_map.pmap->pm_space; tf->tf_pidr1 = tf->tf_pidr2 = pmap_sid2pid(tf->tf_sr0); /* * 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 = PSL_C | PSL_Q | PSL_P | PSL_D | PSL_I /* | PSL_L */ | (curcpu()->ci_psw & PSL_O); /* * 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 + HPPA_FRAME_SIZE; *(register_t*)(osp - HPPA_FRAME_SIZE) = 0; *(register_t*)(osp + HPPA_FRAME_CRP) = (register_t)&switch_trampoline; *(register_t*)(osp) = (osp - HPPA_FRAME_SIZE); sp = osp + HPPA_FRAME_SIZE + 20*4; /* frame + calee-save registers */ *HPPA_FRAME_CARG(0, sp) = (register_t)arg; *HPPA_FRAME_CARG(1, sp) = KERNMODE(func); pcbp->pcb_ksp = sp; }
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); }