/* 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; }
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]); }
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; }
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); }
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; }