Ejemplo n.º 1
0
/* ARGSUSED */
void
sunos32_setregs(struct lwp *l, struct exec_package *pack, vaddr_t stack)
	/* stack:  XXX */
{
	struct trapframe64 *tf = l->l_md.md_tf;
	struct fpstate64 *fs;
	int64_t tstate;
	struct proc *p = l->l_proc;

	/* Don't allow misaligned code by default */
	p->p_md.md_flags &= ~MDP_FIXALIGN;

	/* Mark this as a 32-bit emulation */
	mutex_enter(p->p_lock);
	p->p_flag |= PK_32;
	mutex_exit(p->p_lock);

	/* Setup the ev_out32 hook */
#if NFIRM_EVENTS > 0
	if (ev_out32_hook == NULL)
		ev_out32_hook = ev_out32;
#endif

	/*
	 * Set the registers to 0 except for:
	 *	%o6: stack pointer, built in exec())
	 *	%tstate: (retain icc and xcc and cwp bits)
	 *	%g1: p->p_psstrp (used by crt0)
	 *	%tpc,%tnpc: entry point of program
	 */
	tstate = ((PSTATE_USER32)<<TSTATE_PSTATE_SHIFT) 
		| (tf->tf_tstate & TSTATE_CWP);
	if ((fs = l->l_md.md_fpstate) != NULL) {
		/*
		 * We hold an FPU state.  If we own *the* FPU chip state
		 * we must get rid of it, and the only way to do that is
		 * to save it.  In any case, get rid of our FPU state.
		 */
		if (l == fplwp) {
			savefpstate(fs);
			fplwp = NULL;
		}
		pool_cache_put(fpstate_cache, fs);
		l->l_md.md_fpstate = NULL;
	}
	memset(tf, 0, sizeof *tf);
	tf->tf_tstate = tstate;
	tf->tf_global[1] = (u_int)p->p_psstrp;
	tf->tf_pc = pack->ep_entry & ~3;
	tf->tf_npc = tf->tf_pc + 4;

	stack -= sizeof(struct rwindow32);
	tf->tf_out[6] = stack;
	tf->tf_out[7] = 0;
}
Ejemplo n.º 2
0
void
fill_ddb_regs_from_tf(struct trapframe64 *tf)
{
    extern int savetstate(struct trapstate *);

#ifdef MULTIPROCESSOR
    static db_regs_t ddbregs[CPUSET_MAXNUMCPU];

    curcpu()->ci_ddb_regs = &ddbregs[cpu_number()];
#else
    static db_regs_t ddbregs;

    curcpu()->ci_ddb_regs = &ddbregs;
#endif

    DDB_REGS->db_tf = *tf;
    DDB_REGS->db_fr = *(struct frame64 *)
                      (uintptr_t)tf->tf_out[6];

    if (fplwp) {
        savefpstate(fplwp->l_md.md_fpstate);
        DDB_REGS->db_fpstate = *fplwp->l_md.md_fpstate;
        loadfpstate(fplwp->l_md.md_fpstate);
    }
    /* We should do a proper copyin and xlate 64-bit stack frames, but... */
    /*	if (tf->tf_tstate & TSTATE_PRIV) { .. } */

#if 0
    /* make sure this is not causing ddb problems. */
    if (tf->tf_out[6] & 1) {
        if ((unsigned)(tf->tf_out[6] + BIAS) > (unsigned)KERNBASE)
            DDB_REGS->db_fr = *(struct frame64 *)(tf->tf_out[6] + BIAS);
        else
            copyin((void *)(tf->tf_out[6] + BIAS), &DDB_REGS->db_fr, sizeof(struct frame64));
    } else {
        struct frame32 tfr;
        int i;

        /* First get a local copy of the frame32 */
        if ((unsigned)(tf->tf_out[6]) > (unsigned)KERNBASE)
            tfr = *(struct frame32 *)tf->tf_out[6];
        else
            copyin((void *)(tf->tf_out[6]), &tfr, sizeof(struct frame32));
        /* Now copy each field from the 32-bit value to the 64-bit value */
        for (i=0; i<8; i++)
            DDB_REGS->db_fr.fr_local[i] = tfr.fr_local[i];
        for (i=0; i<6; i++)
            DDB_REGS->db_fr.fr_arg[i] = tfr.fr_arg[i];
        DDB_REGS->db_fr.fr_fp = (long)tfr.fr_fp;
        DDB_REGS->db_fr.fr_pc = tfr.fr_pc;
    }
#endif
    DDB_REGS->db_tl = savetstate(&DDB_REGS->db_ts[0]);
}
Ejemplo n.º 3
0
static inline void
fpusave_cpu(bool save)
{
    struct lwp *l = fplwp;

    if (l == NULL)
        return;

    if (save)
        savefpstate(l->l_md.md_fpstate);
    else
        clearfpstate();

    fplwp = NULL;
}
Ejemplo n.º 4
0
static void
cpu_reset_fpustate(void)
{
	struct fpstate64 *fpstate;
	struct fpstate64 fps[2];

	/* This needs to be 64-byte aligned */
	fpstate = ALIGNFPSTATE(&fps[1]);

	/*
	 * Get the FSR and clear any exceptions.  If we do not unload
	 * the queue here and it is left over from a previous crash, we
	 * will panic in the first loadfpstate(), due to a sequence error,
	 * so we need to dump the whole state anyway.
	 */
	fpstate->fs_fsr = 7 << FSR_VER_SHIFT;	/* 7 is reserved for "none" */
	savefpstate(fpstate);
}
Ejemplo n.º 5
0
void setup_linux_sigframe(struct trapframe *tf, const ksiginfo_t *ksi,
    const sigset_t *mask)
{
	struct lwp *l = curlwp;
	struct proc *p = l->l_proc;
	struct linux_sigframe *sfp, sigframe;
	int onstack, error;
	int fsize, rndfsize;
	int sig = ksi->ksi_signo;
	extern char linux_sigcode[], linux_esigcode[];

	/* Do we need to jump onto the signal stack? */
	onstack = (l->l_sigstk.ss_flags & (SS_DISABLE | SS_ONSTACK)) == 0 &&
		  (SIGACTION(p, sig).sa_flags & SA_ONSTACK) != 0;

	/* Allocate space for the signal handler context.  */
	fsize = sizeof(struct linux_sigframe);
	rndfsize = ((fsize + 15) / 16) * 16;

	if (onstack)
		sfp = (struct linux_sigframe *)
		    ((char *)l->l_sigstk.ss_sp + l->l_sigstk.ss_size);
	else
		sfp = (struct linux_sigframe *)(alpha_pal_rdusp());
	sfp = (struct linux_sigframe *)((char *)sfp - rndfsize);

#ifdef DEBUG
	if ((sigdebug & SDB_KSTACK) && (p->p_pid == sigpid))
		printf("linux_sendsig(%d): sig %d ssp %p usp %p\n", p->p_pid,
		    sig, &onstack, sfp);
#endif /* DEBUG */

	/*
	 * Build the signal context to be used by sigreturn.
	 */
	memset(&sigframe.sf_sc, 0, sizeof(struct linux_sigcontext));
	sigframe.sf_sc.sc_onstack = onstack;
	native_to_linux_old_sigset(&sigframe.sf_sc.sc_mask, mask);
	sigframe.sf_sc.sc_pc = tf->tf_regs[FRAME_PC];
	sigframe.sf_sc.sc_ps = ALPHA_PSL_USERMODE;
	frametoreg(tf, (struct reg *)sigframe.sf_sc.sc_regs);
	sigframe.sf_sc.sc_regs[R_SP] = alpha_pal_rdusp();

	if (l == fpcurlwp) {
		struct pcb *pcb = lwp_getpcb(l);

		alpha_pal_wrfen(1);
		savefpstate(&pcb->pcb_fp);
		alpha_pal_wrfen(0);
		sigframe.sf_sc.sc_fpcr = pcb->pcb_fp.fpr_cr;
		fpcurlwp = NULL;
	}
	/* XXX ownedfp ? etc...? */

	sigframe.sf_sc.sc_traparg_a0 = tf->tf_regs[FRAME_A0];
	sigframe.sf_sc.sc_traparg_a1 = tf->tf_regs[FRAME_A1];
	sigframe.sf_sc.sc_traparg_a2 = tf->tf_regs[FRAME_A2];

	sendsig_reset(l, sig);
	mutex_exit(p->p_lock);
	error = copyout((void *)&sigframe, (void *)sfp, fsize);
	mutex_enter(p->p_lock);

	if (error != 0) {
#ifdef DEBUG
		if ((sigdebug & SDB_KSTACK) && p->p_pid == sigpid)
			printf("sendsig(%d): copyout failed on sig %d\n",
			    p->p_pid, sig);
#endif
		/*
		 * Process has trashed its stack; give it an illegal
		 * instruction to halt it in its tracks.
		 */
		sigexit(l, SIGILL);
		/* NOTREACHED */
	}

	/* Pass pointers to sigcontext in the regs */
	tf->tf_regs[FRAME_A1] = 0;
	tf->tf_regs[FRAME_A2] = (unsigned long)&sfp->sf_sc;

	/* Address of trampoline code.  End up at this PC after mi_switch */
	tf->tf_regs[FRAME_PC] =
	    (u_int64_t)(p->p_psstrp - (linux_esigcode - linux_sigcode));

	/* Adjust the stack */
	alpha_pal_wrusp((unsigned long)sfp);

	/* Remember that we're now on the signal stack. */
	if (onstack)
		l->l_sigstk.ss_flags |= SS_ONSTACK;
}