Date: Sun, 5 Mar 2006 03:07:17 GMT From: Kip Macy <kmacy@FreeBSD.org> To: Perforce Change Reviews <perforce@freebsd.org> Subject: PERFORCE change 92765 for review Message-ID: <200603050307.k2537H9C009821@repoman.freebsd.org>
next in thread | raw e-mail | index | archive | help
http://perforce.freebsd.org/chv.cgi?CH=92765 Change 92765 by kmacy@kmacy_storage:sun4v_work on 2006/03/05 03:06:50 suck back in bits required to make the linker happy Affected files ... .. //depot/projects/kmacy_sun4v/src/sys/sun4v/sun4v/exception.S#16 edit Differences ... ==== //depot/projects/kmacy_sun4v/src/sys/sun4v/sun4v/exception.S#16 (text+ko) ==== @@ -267,10 +267,7 @@ .macro data_miss MAGIC_TRAP_ON - MAGIC_TRAP_ON - MAGIC_TRAP_ON - MAGIC_TRAP_ON - MAGIC_TRAP_ON + .align 32 .endm @@ -999,7 +996,7 @@ brlz,pt %g1, 1f nop wrpr %g0, %g1, %pil - +1: wrpr %g0, %g4, %tnpc rdpr %cwp, %l0 set TSTATE_KERNEL, %l1 @@ -1009,3 +1006,328 @@ END(tl0_trap) END(tl0_intr) + + +/* + * Freshly forked processes come here when switched to for the first time. + * The arguments to fork_exit() have been setup in the locals, we must move + * them to the outs. + */ +ENTRY(fork_trampoline) +#if KTR_COMPILE & KTR_PROC + CATR(KTR_PROC, "fork_trampoline: td=%p (%s) cwp=%#lx" + , %g1, %g2, %g3, 7, 8, 9) + ldx [PCPU(CURTHREAD)], %g2 + stx %g2, [%g1 + KTR_PARM1] + ldx [%g2 + TD_PROC], %g2 + add %g2, P_COMM, %g2 + stx %g2, [%g1 + KTR_PARM2] + rdpr %cwp, %g2 + stx %g2, [%g1 + KTR_PARM3] +9: +#endif + mov %l0, %o0 + mov %l1, %o1 + call fork_exit + mov %l2, %o2 + ba,a %xcc, tl0_ret + nop +END(fork_trampoline) + + + +/* + * The following code is all going to need to be re-written + * but is here to make the linker happy + * + */ + + .comm intrnames, IV_NAMLEN + .comm eintrnames, 0 + + .comm intrcnt, IV_MAX * 8 + .comm eintrcnt, 0 + + +ENTRY(tl1_trap) + illtrap +END(tl1_trap) +/* + * Initiate return to usermode. + * + * Called with a trapframe on the stack. The window that was setup in + * tl0_trap may have been used by "fast" trap handlers that pretend to be + * leaf functions, so all ins and locals may have been clobbered since + * then. + * + * This code is rather long and complicated. + */ +ENTRY(tl0_ret) + /* + * Check for pending asts atomically with returning. We must raise + * the pil before checking, and if no asts are found the pil must + * remain raised until the retry is executed, or we risk missing asts + * caused by interrupts occuring after the test. If the pil is lowered, + * as it is when we call ast, the check must be re-executed. + */ + wrpr %g0, PIL_TICK, %pil + ldx [PCPU(CURTHREAD)], %l0 + lduw [%l0 + TD_FLAGS], %l1 + set TDF_ASTPENDING | TDF_NEEDRESCHED, %l2 + and %l1, %l2, %l1 + brz,a,pt %l1, 1f + nop + + /* + * We have an ast. Re-enable interrupts and handle it, then restart + * the return sequence. + */ + wrpr %g0, 0, %pil + call ast + add %sp, CCFSZ + SPOFF, %o0 + ba,a %xcc, tl0_ret + nop + + /* + * Check for windows that were spilled to the pcb and need to be + * copied out. This must be the last thing that is done before the + * return to usermode. If there are still user windows in the cpu + * and we call a nested function after this, which causes them to be + * spilled to the pcb, they will not be copied out and the stack will + * be inconsistent. + */ +1: ldx [PCB_REG + PCB_NSAVED], %l1 + brz,a,pt %l1, 2f + nop + wrpr %g0, 0, %pil + mov T_SPILL, %o0 + stx %o0, [%sp + SPOFF + CCFSZ + TF_TYPE] + call trap + add %sp, SPOFF + CCFSZ, %o0 + ba,a %xcc, tl0_ret + nop + + /* + * Restore the out and most global registers from the trapframe. + * The ins will become the outs when we restore below. + */ +2: ldx [%sp + SPOFF + CCFSZ + TF_O0], %i0 + ldx [%sp + SPOFF + CCFSZ + TF_O1], %i1 + ldx [%sp + SPOFF + CCFSZ + TF_O2], %i2 + ldx [%sp + SPOFF + CCFSZ + TF_O3], %i3 + ldx [%sp + SPOFF + CCFSZ + TF_O4], %i4 + ldx [%sp + SPOFF + CCFSZ + TF_O5], %i5 + ldx [%sp + SPOFF + CCFSZ + TF_O6], %i6 + ldx [%sp + SPOFF + CCFSZ + TF_O7], %i7 + + ldx [%sp + SPOFF + CCFSZ + TF_G1], %g1 + ldx [%sp + SPOFF + CCFSZ + TF_G2], %g2 + ldx [%sp + SPOFF + CCFSZ + TF_G3], %g3 + ldx [%sp + SPOFF + CCFSZ + TF_G4], %g4 + ldx [%sp + SPOFF + CCFSZ + TF_G5], %g5 + + /* + * Load everything we need to restore below before disabling + * interrupts. + */ + ldx [%sp + SPOFF + CCFSZ + TF_FPRS], %l0 + ldx [%sp + SPOFF + CCFSZ + TF_GSR], %l1 + ldx [%sp + SPOFF + CCFSZ + TF_TNPC], %l2 + ldx [%sp + SPOFF + CCFSZ + TF_TPC], %l3 + ldx [%sp + SPOFF + CCFSZ + TF_TSTATE], %l4 + ldx [%sp + SPOFF + CCFSZ + TF_Y], %l5 + ldx [%sp + SPOFF + CCFSZ + TF_WSTATE], %l6 + + /* + * Disable interrupts to restore the special globals. They are not + * saved and restored for all kernel traps, so an interrupt at the + * wrong time would clobber them. + */ + wrpr %g0, PSTATE_NORMAL, %pstate + + ldx [%sp + SPOFF + CCFSZ + TF_G6], %g6 + ldx [%sp + SPOFF + CCFSZ + TF_G7], %g7 + +#if 0 + /* + * Switch to alternate globals. This frees up some registers we + * can use after the restore changes our window. + */ + wrpr %g0, PSTATE_ALT, %pstate +#endif + /* + * Drop %pil to zero. It must have been zero at the time of the + * trap, since we were in usermode, but it was raised above in + * order to check for asts atomically. We have interrupts disabled + * so any interrupts will not be serviced until we complete the + * return to usermode. + */ + wrpr %g0, 0, %pil + + /* + * Save %fprs in an alternate global so it can be restored after the + * restore instruction below. If we restore it before the restore, + * and the restore traps we may run for a while with floating point + * enabled in the kernel, which we want to avoid. + */ + mov %l0, %g1 + + /* + * Restore %fsr and %gsr. These need floating point enabled in %fprs, + * so we set it temporarily and then clear it. + */ + wr %g0, FPRS_FEF, %fprs + ldx [%sp + SPOFF + CCFSZ + TF_FSR], %fsr + wr %l1, 0, %gsr + wr %g0, 0, %fprs + + /* + * Restore program counters. This could be done after the restore + * but we're out of alternate globals to store them in... + */ + wrpr %l2, 0, %tnpc + wrpr %l3, 0, %tpc + + /* + * Save %tstate in an alternate global and clear the %cwp field. %cwp + * will be affected by the restore below and we need to make sure it + * points to the current window at that time, not the window that was + * active at the time of the trap. + */ + andn %l4, TSTATE_CWP_MASK, %g2 + + /* + * Restore %y. Could also be below if we had more alternate globals. + */ + wr %l5, 0, %y + + /* + * Setup %wstate for return. We need to restore the user window state + * which we saved in wstate.other when we trapped. We also need to + * set the transition bit so the restore will be handled specially + * if it traps, use the xor feature of wrpr to do that. + */ +#if 0 + srlx %l6, WSTATE_OTHER_SHIFT, %g3 + wrpr %g3, WSTATE_TRANSITION, %wstate +#endif + /* + * Setup window management registers for return. If not all user + * windows were spilled in the kernel %otherwin will be non-zero, + * so we need to transfer it to %canrestore to correctly restore + * those windows. Otherwise everything gets set to zero and the + * restore below will fill a window directly from the user stack. + */ + rdpr %otherwin, %o0 + wrpr %o0, 0, %canrestore + wrpr %g0, 0, %otherwin + wrpr %o0, 0, %cleanwin + + /* + * Now do the restore. If this instruction causes a fill trap which + * fails to fill a window from the user stack, we will resume at + * tl0_ret_fill_end and call back into the kernel. + */ + restore +tl0_ret_fill: + + /* + * We made it. We're back in the window that was active at the time + * of the trap, and ready to return to usermode. + */ + + /* + * Restore %frps. This was saved in an alternate global above. + */ + wr %g1, 0, %fprs + + /* + * Fixup %tstate so the saved %cwp points to the current window and + * restore it. + */ + rdpr %cwp, %g4 + wrpr %g2, %g4, %tstate + + /* + * Restore the user window state. The transition bit was set above + * for special handling of the restore, this clears it. + */ + wrpr %g3, 0, %wstate + +#if KTR_COMPILE & KTR_TRAP + CATR(KTR_TRAP, "tl0_ret: td=%#lx pil=%#lx pc=%#lx npc=%#lx sp=%#lx" + , %g2, %g3, %g4, 7, 8, 9) + ldx [PCPU(CURTHREAD)], %g3 + stx %g3, [%g2 + KTR_PARM1] + rdpr %pil, %g3 + stx %g3, [%g2 + KTR_PARM2] + rdpr %tpc, %g3 + stx %g3, [%g2 + KTR_PARM3] + rdpr %tnpc, %g3 + stx %g3, [%g2 + KTR_PARM4] + stx %sp, [%g2 + KTR_PARM5] +9: +#endif + + /* + * Return to usermode. + */ + retry +tl0_ret_fill_end: + +#if KTR_COMPILE & KTR_TRAP + CATR(KTR_TRAP, "tl0_ret: fill magic ps=%#lx ws=%#lx sp=%#lx" + , %l0, %l1, %l2, 7, 8, 9) + rdpr %pstate, %l1 + stx %l1, [%l0 + KTR_PARM1] + stx %l5, [%l0 + KTR_PARM2] + stx %sp, [%l0 + KTR_PARM3] +9: +#endif + + /* + * The restore above caused a fill trap and the fill handler was + * unable to fill a window from the user stack. The special fill + * handler recognized this and punted, sending us here. We need + * to carefully undo any state that was restored before the restore + * was executed and call trap again. Trap will copyin a window + * from the user stack which will fault in the page we need so the + * restore above will succeed when we try again. If this fails + * the process has trashed its stack, so we kill it. + */ + + /* + * Restore the kernel window state. This was saved in %l6 above, and + * since the restore failed we're back in the same window. + */ + wrpr %l6, 0, %wstate + +#if 0 + /* + * Restore the normal globals which have predefined values in the + * kernel. We clobbered them above restoring the user's globals + * so this is very important. + * XXX PSTATE_ALT must already be set. + */ + wrpr %g0, PSTATE_ALT, %pstate + mov PCPU_REG, %o1 + wrpr %g0, PSTATE_NORMAL, %pstate + mov %o0, PCB_REG + mov %o1, PCPU_REG + wrpr %g0, PSTATE_KERNEL, %pstate +#endif + /* + * Simulate a fill trap and then start the whole return sequence over + * again. This is special because it only copies in 1 window, not 2 + * as we would for a normal failed fill. This may be the first time + * the process has been run, so there may not be 2 windows worth of + * stack to copyin. + */ + mov T_FILL_RET, %o0 + stx %o0, [%sp + SPOFF + CCFSZ + TF_TYPE] + call trap + add %sp, SPOFF + CCFSZ, %o0 + ba,a %xcc, tl0_ret + nop +END(tl0_ret) +
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200603050307.k2537H9C009821>