Exemplo n.º 1
0
void
userret(struct lwp *l)
{
#if defined(__PROG32) && defined(ARM_MMU_EXTENDED)
	/*
	 * If our ASID got released, access via TTBR0 will have been disabled.
	 * So if it is disabled, activate the lwp again to get a new ASID.
	 */
#ifdef __HAVE_PREEMPTION
	kpreempt_disable();
#endif
	KASSERT(curcpu()->ci_pmap_cur == l->l_proc->p_vmspace->vm_map.pmap);
	if (__predict_false(armreg_ttbcr_read() & TTBCR_S_PD0)) {
		pmap_activate(l);
	}
	KASSERT(!(armreg_ttbcr_read() & TTBCR_S_PD0));
#ifdef __HAVE_PREEMPTION
	kpreempt_enable();
#endif
#endif

	/* Invoke MI userret code */
	mi_userret(l);

#if defined(__PROG32) && defined(DIAGNOSTIC)
	KASSERT(VALID_R15_PSR(lwp_trapframe(l)->tf_pc,
	    lwp_trapframe(l)->tf_spsr));
#endif
}
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;
	struct switchframe *sf;

#if 0
	printf("cpu_lwp_fork: %p -> %p\n", p1, p2);
#endif
	pcb1 = lwp_getpcb(l1);
	pcb2 = lwp_getpcb(l2);

	/* Copy the pcb */
	*pcb2 = *pcb1;

	/* pmap_activate(l2); XXX Other ports do.  Why?  */

	/* Set up the kernel stack */
	tf = (struct trapframe *)(uvm_lwp_getuarea(l2) + USPACE) - 1;
	sf = (struct switchframe *)tf - 1;
	/* Duplicate old process's trapframe (if it had one) */
	if (lwp_trapframe(l1) == NULL)
		memset(tf, 0, sizeof(*tf));
	else
		*tf = *lwp_trapframe(l1);
	/* If specified, give the child a different stack. */
	if (stack != NULL)
		tf->tf_usr_sp = (u_int)stack + stacksize;
	lwp_settrapframe(l2, tf);
	/* Fabricate a new switchframe */
	memset(sf, 0, sizeof(*sf));

	sf->sf_r13 = (register_t)tf; /* Initial stack pointer */
	sf->sf_pc  = (register_t)lwp_trampoline | R15_MODE_SVC;

	lwp_settrapframe(l2, tf);
	pcb2->pcb_sf = sf;
	pcb2->pcb_onfault = NULL;
	sf->sf_r4 = (register_t)func;
	sf->sf_r5 = (register_t)arg;
}
Exemplo n.º 3
0
int
compat_13_sys_sigreturn(struct lwp *l, const struct compat_13_sys_sigreturn_args *uap, register_t *retval)
{
    /* {
    	syscallarg(struct sigcontext13 *) sigcntxp;
    } */
    struct sigcontext13 *scp, context;
    struct trapframe * const tf = lwp_trapframe(l);
    struct proc * const p = l->l_proc;
    sigset_t mask;

    /*
     * The trampoline code hands us the context.
     * It is unsafe to keep track of it ourselves, in the event that a
     * program jumps out of a signal handler.
     */
    scp = SCARG(uap, sigcntxp);
    if (copyin((void *)scp, &context, sizeof(*scp)) != 0)
        return (EFAULT);

    /*
     * Make sure the processor mode has not been tampered with and
     * interrupts have not been disabled.
     */
    if (!VALID_R15_PSR(context.sc_pc, context.sc_spsr))
        return EINVAL;

    /* Restore register context. */
    tf->tf_r0    = context.sc_r0;
    tf->tf_r1    = context.sc_r1;
    tf->tf_r2    = context.sc_r2;
    tf->tf_r3    = context.sc_r3;
    tf->tf_r4    = context.sc_r4;
    tf->tf_r5    = context.sc_r5;
    tf->tf_r6    = context.sc_r6;
    tf->tf_r7    = context.sc_r7;
    tf->tf_r8    = context.sc_r8;
    tf->tf_r9    = context.sc_r9;
    tf->tf_r10   = context.sc_r10;
    tf->tf_r11   = context.sc_r11;
    tf->tf_r12   = context.sc_r12;
    tf->tf_usr_sp = context.sc_usr_sp;
    tf->tf_usr_lr = context.sc_usr_lr;
    tf->tf_svc_lr = context.sc_svc_lr;
    tf->tf_pc    = context.sc_pc;
    tf->tf_spsr  = context.sc_spsr;

    mutex_enter(p->p_lock);

    /* Restore signal stack. */
    if (context.sc_onstack & SS_ONSTACK)
        l->l_sigstk.ss_flags |= SS_ONSTACK;
    else
        l->l_sigstk.ss_flags &= ~SS_ONSTACK;

    /* Restore signal mask. */
    native_sigset13_to_sigset(&context.sc_mask, &mask);
    (void) sigprocmask1(l, SIG_SETMASK, &mask, 0);

    mutex_exit(p->p_lock);

    return (EJUSTRETURN);
}
Exemplo n.º 4
0
/*
 * Finish a fork operation, with LWP l2 nearly set up.
 *
 * Copy and update the pcb and trapframe, making the child ready to run.
 *
 * Rig the child's kernel stack so that it will start out in
 * lwp_trampoline() which will call the specified func with the argument arg.
 *
 * If an alternate user-level stack is requested (with non-zero values
 * in both the stack and stacksize args), set up the user stack pointer
 * accordingly.
 */
void
cpu_lwp_fork(struct lwp *l1, struct lwp *l2, void *stack, size_t stacksize,
    void (*func)(void *), void *arg)
{
	struct switchframe *sf;
	vaddr_t uv;

	const struct pcb * const pcb1 = lwp_getpcb(l1);
	struct pcb * const pcb2 = lwp_getpcb(l2);

#ifdef PMAP_DEBUG
	if (pmap_debug_level > 0)
		printf("cpu_lwp_fork: %p %p %p %p\n", l1, l2, curlwp, &lwp0);
#endif	/* PMAP_DEBUG */

	/* Copy the pcb */
	*pcb2 = *pcb1;

#ifdef FPU_VFP
	/*
	 * Disable the VFP for a newly created LWP but remember if the
	 * VFP state is valid.
	 */
	pcb2->pcb_vfp.vfp_fpexc &= ~VFP_FPEXC_EN;
#endif

	/*
	 * Set up the kernel stack for the process.
	 * Note: this stack is not in use if we are forking from p1
	 */
	uv = uvm_lwp_getuarea(l2);
	pcb2->pcb_ksp = uv + USPACE_SVC_STACK_TOP;

#ifdef STACKCHECKS
	/* Fill the kernel stack with a known pattern */
	memset((void *)(uv + USPACE_SVC_STACK_BOTTOM), 0xdd,
	    (USPACE_SVC_STACK_TOP - USPACE_SVC_STACK_BOTTOM));
#endif	/* STACKCHECKS */

#ifdef PMAP_DEBUG
	if (pmap_debug_level > 0) {
		printf("l1: pcb=%p pid=%d pmap=%p\n",
		    pcb1, l1->l_lid, l1->l_proc->p_vmspace->vm_map.pmap);
		printf("l2: pcb=%p pid=%d pmap=%p\n",
		    pcb2, l2->l_lid, l2->l_proc->p_vmspace->vm_map.pmap);
	}
#endif	/* PMAP_DEBUG */

	struct trapframe *tf = (struct trapframe *)pcb2->pcb_ksp - 1;
	lwp_settrapframe(l2, tf);
	*tf = *lwp_trapframe(l1);

	/*
	 * If specified, give the child a different stack (make sure
	 * it's 8-byte aligned).
	 */
	if (stack != NULL)
		tf->tf_usr_sp = ((vaddr_t)(stack) + stacksize) & -8;

	sf = (struct switchframe *)tf - 1;
	sf->sf_r4 = (u_int)func;
	sf->sf_r5 = (u_int)arg;
	sf->sf_r7 = PSR_USR32_MODE;		/* for returning to userspace */
	sf->sf_sp = (u_int)tf;
	sf->sf_pc = (u_int)lwp_trampoline;
	pcb2->pcb_ksp = (u_int)sf;
}