\ ========== Copyright Header Begin ========================================== \ \ Hypervisor Software File: reenter.fth \ \ Copyright (c) 2006 Sun Microsystems, Inc. All Rights Reserved. \ \ - Do no alter or remove copyright notices \ \ - Redistribution and use of this software in source and binary forms, with \ or without modification, are permitted provided that the following \ conditions are met: \ \ - Redistribution of source code must retain the above copyright notice, \ this list of conditions and the following disclaimer. \ \ - Redistribution in binary form must reproduce the above copyright notice, \ this list of conditions and the following disclaimer in the \ documentation and/or other materials provided with the distribution. \ \ Neither the name of Sun Microsystems, Inc. or the names of contributors \ may be used to endorse or promote products derived from this software \ without specific prior written permission. \ \ This software is provided "AS IS," without a warranty of any kind. \ ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, \ INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A \ PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN \ MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR \ ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR \ DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN \ OR ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR \ FOR DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE \ DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, \ ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF \ SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. \ \ You acknowledge that this software is not designed, licensed or \ intended for use in the design, construction, operation or maintenance of \ any nuclear facility. \ \ ========== Copyright Header End ============================================ id: @(#)reenter.fth 1.22 07/06/22 purpose: copyright: Copyright 2007 Sun Microsystems, Inc. All Rights Reserved copyright: Use is subject to license terms. \ Ways to enter the Forth interpreter, and their implications: \ a) Power up - no autoboot \ Entry mechanism: prom-cold-code, which is entered from the boot-state \ reset vector, distinguished this from a watchdog reset by looking \ at the watchdog bit in the system error register. prom-cold-code \ then initializes the machine and executes the Forth startup \ sequence. \ Action: perform the startup initialization sequence, then boot \ the operating system if autoboot is specified in the configuration. \ Otherwise enter the text interpreter. \ b) Power up - abort key \ Action: Finish initialization procedure, but enter interpreter \ instead of autoboot \ c) Breakpoint (= single step) \ Entry mechanism: the trap table entry reads the psr into %l0 and \ jumps to save-state . save-state saves %l0 into the error-reset-trap \ field of the cpu-state save area. \ Signature: The trap type field of the saved tbr indicates the \ breakpoint trap vector, the error-reset-trap field of the cpu-state save \ area contains a valid psr value (as opposed to -1; see the \ "Error reset" case), and no other special conditions are present \ (see "exittomon", "abortent") \ Action: perform the action indicated by the "handle-breakpoint" \ routine; usually disassembles the breakpointed instruction and \ enters the text interpreter \ d) Error trap (e.g. Data Access Exception) \ Entry mechanism: the trap table entry reads the psr into %l0 and \ jumps to save-state . save-state saves %l0 into the error-reset-trap \ field of the cpu-state save area. \ Signature: The trap type field of the saved tbr indicates the \ breakpoint trap vector, the error-reset-trap field of the cpu-state save \ area contains a valid psr value (as opposed to -1; see the \ "Error reset" case), and no other special conditions are present \ (see "exittomon", "abortent") \ Action: display exception name and enter text interpreter \ e) Exittomon - Return from Unix - don't expect to re-enter \ Entry mechanism: sun4m/machdep.c:halt() calls romp->v_exit_to_mon, \ which resolves to reenter.fth:reenter . "reenter" executes the \ breakpoint trap instruction, which proceeds as in the "breakpoint" \ case. \ Signature: This looks almost like the "Breakpoint" case, and is \ distinguised from that case by the fact that the saved %pc value \ indicates the address of the trap instruction within the "reenter" \ routine. \ Action: Display "Type 'go' to resume", then enter text interpreter \ Problem: kadb may have usurped the breakpoint trap table entry \ Idea: Maybe instead of start_mon_clock(), stop_mon_clock(), we should \ provide romvecs for this, or maybe the monitor should just do it \ automatically whenever the interpreter is entered or one of the \ the monitor's I/O routines (maybe just mayget) is called. (No, just \ mayget() is insufficient, because we could lose characters when \ scrolling the screen. \ Note: Unix displays a message through the PROM's printf routine \ before calling romp->v_exit_to_mon. The message depends on \ the reason for the halt: \ "Halted" Executed from sun4m/machdep.c:boot(), from \ reboot system call entry (in os/kern_xxx.c), \ but only if RB_HALT flag from the user's \ parameters to the system call is set. \ spl6() is performed before calling halt() \ "bootflags" The RB_HALT flag was set when Unix parsed the \ boot flags. Restartable. spl6() NOT called \ (Is that the right thing?) \ "system map tables too large" \ Unix has an internal configuration problem \ "no memory" Unix was too big for the available phys. memory \ \ Note: Unix starts the monitor clock before calling romp->v_exit_to_mon \ Note: Unix does not intend to be restarted in most cases, but \ in the "bootflags" case above, restarting is reasonable. \ Halt() remembers to stop the monitor clock if exit_to_mon returns. \ \ f) Abortent - keyboard abort from Unix (L1-A or Break) (continuable) \ Entry mechanism: either sundev/zs_async.c or sundev/kbd.c calls \ sun4m/locore.s:montrap(romp->v_abortent), which then calls that \ abortent routine. Currently, the abortent romvec resolves to \ reenter.fth:reeenter, the same as for "Exittomon" \ Signature: Currently, this is indistinguishable from the "Exittomon" \ case, unless Forth is willing to dig around in the window registers \ to identify the "montrap()" return address (a silly way to do it; \ it would be easier to provide a separate "abort-reenter" routine). \ Action: Currently the same as for "Exittomon" \ Suggestion: the action should be similar to "L1-A when Forth running" \ Note: if kadb is installed (Unix saw "-d" flag), kadb is entered \ instead of the monitor. \ Note: Execution of Unix is frequently resumed after this kind of abort \ Note: Unix does NOT start the monitor clock before calling \ romp->v_abortent \ \ g) Bootme - return from Unix with auto-reboot \ Entry mechanism: sun4m/machdep.c:boot(), which is called from the \ reboot system call code in os/kern_xxx.c. boot() calls \ romp->v_boot_me, which calls a Forth entry resolving to \ bootparams.fth:boot-me \ Note: Never returns to Unix; instead reboots the system \ Note: Monitor clock has been started at spl6() (pil 13). \ Note: Argument is a C string which is either "", "-s", or the argument \ to the reboot user command \ Note: Doesn't enter the Forth text interpreter \ \ h) Callvec - call Unix subroutine which then returns back to Forth \ Entry mechanism: Forth calls a subroutine whose address has been \ exported by Unix. That subroutine returns, reentering the \ Forth word (callvec or sync) from which it was called. \ Note: Unix doesn't do anything to restore it's state. Maybe this is \ wrong. Perhaps Unix should be in charge of setting up its own \ stack, context, trap table, and interrupts again? \ Note: This is usually executed after a keyboard abort or a watchdog. \ \ i) fwritestr - terminal emulator called from Unix \ Entry mechanism: Unix calls either "putchar()", "mayput()", or \ "fwritestr()". putchar() and mayput() are C subroutines which \ themselves call "fwritestr()". fwritestr() is a C to Forth entry \ point, which establishes a temporary Forth environment on the \ C stack, then calls a Forth word. \ Note: When executing fwritestr(), we can lose keyboard characters \ if Unix has disabled the Forth level 14 clock handler. We need \ to make sure that Unix leaves that handler enabled during startup \ up until the point where Unix takes over the keyboard. \ \ j) L1-A or break from keyboard when Forth is running \ Entry mechanism: The level 14 clock interrupt handler checks for an \ abort (L1-A from the keyboard or break from a tty) and sets the \ "aborted?" variable if one is seen. Just before the assembly \ language part of the interrupt handler returns, it checks \ "aborted?", and if it is set, the handler jumps to save-state \ instead of returning. The CPU state at that point has been \ restored to the same state that existed just when the interrupt \ handler was entered, i.e. as if the trap had directly vectored \ to "save-state" instead of to the interrupt handler. That way, \ the user does not see any artifacts of the interrupt handler itself. \ Signature: The "aborted?" variable is set. Otherwise looks like a \ a breakpoint. \ Action: Displays "Keyboard abort. Type 'go' to resume" \ \ k) L1-A from keyboard with interrupts off and polling mayget() \ Entry mechanism: an application is calling the PROM's mayget() \ routine in order to get a characters. Level 14 interrupts are \ turned off. The input device is the Sun keyboard. mayget() \ call key_check() to poll the keyboard. The key is determined \ to be the A of an L1-A sequence. key_check() calls _enterforth \ == reenter , which sets the establishes Forth's trap table and \ executes a trap #7f instruction. \ Signature: This looks like the "Abortent" case above. If necessary \ it could be distinguished by looking on the C stack to see the \ interruption of the key_check routine. \ Action: Displays "Type 'go' to resume" \ \ l) From a watchdog reset \ Entry mechanism: prom-cold-code, which is entered from the boot-state \ reset vector, destinguished this from a power-on reset by looking \ at the watchdog bit in the system error register. prom-cold-code \ then puts a discernable value (-1) in %l0, jumps to save-state, \ and save-state saves %l0 in the cpu-state area. \ Signature: the "error-reset-trap" field in the cpu-state area contains -1. \ Otherwise looks like a breakpoint. \ Action: If watchdog-reboot? is set, execute the autoboot sequence, \ otherwise enter the text interpreter. \ Enter the monitor with no complaints or error messages. only forth also hidden also forth definitions headerless code reclaim-machine ( -- ) %g0 h# 14 wrpstate \ IE=0, FPU=1, PRIV=1 [ifdef] SUN4V %g0 %o0 move %g0 %o1 move %g0 h# 20 %o5 add \ MMU_TSB_CTX0 %g0 h# 80 always htrapif %g0 %o0 move %g0 %o1 move %g0 h# 21 %o5 add \ MMU_TSB_CTXNON0 %g0 h# 80 always htrapif [then] trap-table %o0 set %o0 0 wrtba %g0 h# f wrpil %g0 h# 16 wrpstate \ IE=1, FPU=1, PRIV=1 c; label exittomon flushw \ Undo the effects of "fentry" because \ of the Client Interface Service EXIT \ We don't want to depend on the data \ stack pointer being the same, because \ the routine may have left a return value \ on the stack. %o6 V9_SP_BIAS d# 16 na+ sp nget %o6 V9_SP_BIAS d# 24 na+ rp nget \ Restore these in case of multiple levels of cross-language calls; \ if the Forth word that was just executed called a C subroutine, \ then saved-sp and saved-rp could have been changed. sp 'user saved-sp nput rp 'user saved-rp nput \ Restore the Globals %o6 V9_SP_BIAS d# 17 na+ %g1 nget %o6 V9_SP_BIAS d# 18 na+ %g2 nget %o6 V9_SP_BIAS d# 19 na+ %g3 nget %o6 V9_SP_BIAS d# 20 na+ %g4 nget %o6 V9_SP_BIAS d# 21 na+ %g5 nget %o6 V9_SP_BIAS d# 22 na+ %g6 nget %o6 V9_SP_BIAS d# 23 na+ %g7 nget \ Back to the previous frame %g0 0 %g0 restore \ Save the client program's trap base register %o0 rdtba %o1 rdpstate %o1 2 %o2 andn %o2 0 wrpstate \ Set the trap base register to Forth's trap table trap-table %o2 set %o2 0 wrtba nop nop nop begin %g0 h# 7f always trapif again \ Not restartable; keep exiting nop end-code create exittomon-end label reenter ( -- ) flushw \ Undo the effects of "fentry" because \ of the Client Interface Service ENTER \ We don't want to depend on the data \ stack pointer being the same, because \ the routine may have left a return value \ on the stack. %o6 V9_SP_BIAS d# 16 na+ sp nget %o6 V9_SP_BIAS d# 24 na+ rp nget \ Restore these in case of multiple levels of cross-language calls; \ if the Forth word that was just executed called a C subroutine, \ then saved-sp and saved-rp could have been changed. sp 'user saved-sp nput rp 'user saved-rp nput \ Restore the Globals %o6 V9_SP_BIAS d# 17 na+ %g1 nget %o6 V9_SP_BIAS d# 18 na+ %g2 nget %o6 V9_SP_BIAS d# 19 na+ %g3 nget %o6 V9_SP_BIAS d# 20 na+ %g4 nget %o6 V9_SP_BIAS d# 21 na+ %g5 nget %o6 V9_SP_BIAS d# 22 na+ %g6 nget %o6 V9_SP_BIAS d# 23 na+ %g7 nget \ Back to the previous frame %g0 0 %g0 restore \ Save the client program's trap base register %o0 rdtba %o1 rdpstate %o1 2 %o2 andn %o2 0 wrpstate \ Set the trap base register to Forth's trap table trap-table %o2 set %o2 0 wrtba nop nop nop \ %o0 : Original %tba \ %o1 : Original %pstate %g0 h# 7f always trapif \ %o0 : %tba \ %o1 : %pstate \ Restore the client's trap base register %o0 0 wrtba nop nop nop %o1 0 wrpstate %o7 8 %g0 jmpl nop end-code create reenter-end : .go-message ( -- ) \ Restarting is only possible if the state that was first saved \ is from a restartable exception. state-valid @ -1 = already-go? and if restartable? on ['] interpret behavior ['] (interpret = if ." Type 'go' to resume" cr then then ; headers 0 >debugger-hook per-cpu-defer: debugger-hook \ \ KADB uses this *and* the per cpu version! \ : init-debugger-hook ( xt -- ) ['] debugger-hook 3 perform-action ; stand-init: Init debugger-hook ['] noop init-debugger-hook ; headerless defer rearm-alarms ' noop is rearm-alarms : reset-debugger-hook ( -- ) ['] noop to debugger-hook ; : enter-debugger ( -- ) addr debugger-hook token@ reset-debugger-hook execute ; h# 3 constant xir-trap# : is-xir-trap? ( -- flag ) last-trap# xir-trap# = ; : is-breakpoint-trap? ( -- flag ) last-trap# breakpoint-trap# = ; : inside? ( label end -- flag ) %pc -rot within ; \ Hooks to take care of special platform specific handling. defer xir-trap-hook ' noop is xir-trap-hook defer exittomon-hook ' noop is exittomon-hook defer reenter-hook ( -- ) ' noop is reenter-hook : .trap ( -- ) talign \ Hack; recover in case dp is misaligned aborted? @ if aborted? off rearm-alarms enter-debugger hex cr .go-message exit then is-xir-trap? if reset-debugger-hook xir-trap-hook then is-breakpoint-trap? 0= if enter-debugger (do-last-trap) exit then \ We want to stay at the 'ok' prompt \ so, uninstall the debugger-hook reset-debugger-hook exittomon exittomon-end inside? if obp-control-relinquished? if client-exited-chain else \ Client program dropped to ok-prompt by unsuccessful boot client-fail-exited-chain then false to obp-control-relinquished? exittomon-hook ." Program terminated" cr exit then reenter reenter-end inside? if reenter-hook .go-message %o0 to %tba %o1 to %pstate then ; : (restart ( -- ) \ If the PC is pointing to the trap instruction in "reenter", \ adjust %pc and %npc to skip that trap instruction. reenter reenter-end inside? if 0w 0 to %o2 %pc la1+ to %pc %npc la1+ to %npc then (crestart ; : mp-ok ( -- ) mid@ <# ascii } hold u#s ascii { hold u#> type ." ok " ; : mp-system? ( -- n-1 ) -1 max-mondo-target# 0 ?do i mid-ok? if i >cpu-struct >cpu-status @ if 1+ then then loop ; : ?mp-prompt ( -- ) ['] "ok" is (ok) mp-system? if ['] mp-ok is (ok) then ; stand-init: Install .exception ['] .trap is .exception ; headers only forth also definitions