예제 #1
0
파일: vm_machdep.c 프로젝트: MarginC/kame
void
cpu_lwp_free(struct lwp *l, int proc)
{

	/* Flush the LWP out of the FPU. */
	hppa_fpu_flush(l);
}
예제 #2
0
파일: vm_machdep.c 프로젝트: MarginC/kame
void
cpu_swapout(struct lwp *l)
{

	/* Flush this LWP out of the FPU. */
	hppa_fpu_flush(l);
}
예제 #3
0
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;
}
예제 #4
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);
}
예제 #5
0
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;
}
예제 #6
0
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;
}
예제 #7
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);
}
예제 #8
0
파일: vm_machdep.c 프로젝트: MarginC/kame
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);
}