.TITLE ROLLOUT - SYSTEM ROLLOUT PROGRAM .IDENT /02/ ;++ ; ; Facility: Special Rollout System Checkpoint Routine ; ; Abstract: ROLLOUT contains the code necessary to save ; the volatile state necessary for restart when ; ROLLIN is executed. Operationally, it saves ; the contents of physical memory to the system ; dump file, SYSDUMP.DMP; after emulating ; EXE$POWERFAIL. ; ; Enviornment: MODE=User , IPL=0 ; ; Privilages: CHMK ; ; Author: W. CRAIG BLASINGAME - Seattle Software Services ; Created under PL90 contract - Date: 30-Aug-79 ; ; Modified by: ; ; Version: 1 ; ;-- ; ; Include files: ; $IPLDEF ; DEFINE INTERRUPT PRIORITY LEVELS $PRDEF ; DEFINE PROCESSOR REGISTER NUMBERS $RPBDEF ; DEFINE RESTART PARAMETER BLOCK OFFSETS $SSDEF ; ERROR MESSAGES ; ; MACROS: .MACRO ERROR NO .NARG TEST TSTL (SP)+ ; SKIP R0 POPR #^M .IF NE TEST MOVL NO,R0 .ENDC REI .ENDM ; ; ; Equated Symbols: INTSTK = 1 ; Flag on SCB to vector to interrupt stack RESTRT_POWERUP = 3 ; Power recovery restart code RPB_SAVED_Q1 = RPB$K_LENGTH ; Offset to saved RPB values ; BASE:+4 to BASE:+12 RPB_SAVED_Q2 = RPB_SAVED_Q1+8 ; Offset to saved RPB values ; BASE:+12 to BASE:+20 RPB_PHY_IOVEC = RPB_SAVED_Q2+8 ; Offset to stored address of bootdriver ; in the ROLLEDOUT system (physical) RPB_ROLLIN_CODE = RPB_PHY_IOVEC+4 ; Offset to HALT instruction in ROLLIN ; ; Own Storage: ; ; .PAGE .PSECT YROLLD,LONG,RD,WRT,NOEXE ;DATA .PSECT YROLL,LONG,PIC,SHR,NOWRT ;CODE .SBTTL ROLL_MAIN - MAIN ROUTINE OF ROLLOUT/IN PROGRAM ; ROLL_MAIN is contained within the FORTRAN Routine ROLLMAIN .SBTTL ROLL_PFAIL - TRANSFER TO INTERRUPT STACK ROUTINE ;++ ; ; Functional Description: ; During ROLLOUT: ; ROLL_PFAIL is entered from ROLLOUT_MAIN via a CHMK. ; It establishes ROLL_PFAIL_IS as the interrupt service ; routine for IPL-31 Kernal Stack Invalid exceptions, then causes ; an exception by cleaning the KSP and depositing @SP . ; During ROLLIN: ; ROLL_PFAIL is reentered via a REI from EXE$RESTART. ; It replaces the SCB vector displaced during ROLLOUT and ; also removes the rollout code from the System Restart ; Parameter Block (RPB). ; ; Calling Sequence: CHMK ; ; Input Parameters: ; 00(SP) - PC at time of CHMK, In ROLLOUT_MAIN ; 04(SP) - PSL (User Mode) at time of CHMK ; AP - 0 (no arguments) ; ; Implicit Inputs: ; All processor registers ; System Control Block Base (SCBB) located via SCB$AL_BASE ; Restart Parameter Block located via EXE$GL_RPB. ; ;-- - tart Pa ROLL_PFAIL:: .WORD ^M 1$: DSBINT ; Set IPL to 31 MOVAL @#SCB$AL_BASE,R1 ; System Control Block Base Address MOVL ^X08(R1),R11 ; Store current contents of KSNV vector. MOVAL ROLL_PFAIL_IS+INTSTK,- ; Establish new interrupt service routine. ^X08(R1) MFPR #PR$_KSP,R10 ; Save contents of stack pointer MTPR #0,#PR$_KSP ; ; Make it invalid CLRL (SP) ; Cause execption ; ; Interrupt occurs here. ROLL_PFAIL_IS is entered at ; IPL=31 on the Interrupt Stack. ; Control will return to the next instruction during ; system ROLLIN. ; R0 = 1 INDICATES SUCCESS 5$: MOVZBL #RPB$K_LENGTH,R5 ; Establish offset in RPB of ROLLOUT Code. MOVL @#EXE$GL_RPB,R6 ; Virtual address of RPB ADDL R5,R6 ; Point to code area 10$: MOVL R5,(R6)+ ; Move position marker in ADDL2 S^#4,R5 ; Point R5 to next long word. CMPL #^X200,R5 ; Branch if still addressing RPB page BNEQ 10$ BLBC R0,30$ ; BRANCH IF ERROR 20$: MFPR #PR$_TXCS,R6 ; Get console transmitter status BBC #7,R6,20$ ; Wait until ready MTPR #^XF04,#PR$_TXDB; Send code to clear warmstart disable flag 21$: MFPR #PR$_TXCS,R6 ; Get status BBC #7,R6,21$ ; Wait until done ; Note: ; This is to emulate what EXE$INIT would have done. ; When EXE$RESTART sent ^XF03 to clear warmstart, ; it actually cleared coldstart since we got ; to that code via cold boot and not through ; the restart referee. 30$: ENBINT ; Set IPL back to user level. RET ; Return to user level in ROLLIN_MAIN .PAGE .SBTTL ROLL_PFAIL_IS - POWERFAIL IMMULATION ROUTINE ;++ ; Functional Description: ; ROLL_PFAIL_IS is entered on the interrupt stack with ; IPL=31 as a result of a kernal stack not valid exception. ; The routine immulates EXE$POWERFAIL by saving the volitile machine ; registers to the Restart Parameter Block (RPB). It also ; inserts code in the unused portion of the RPB to be used ; during ROLLIN. ; ; Calling Sequence: ; Software interrupt through vector ^X08 in the SCB. ; ; Input Parameters: ; 00(SP) - PC at time of interrupt ; 04(SP) - PSL at time of interrupt ; ; Implicit Parameters: ; ALL registers and Processor registers ; Restart Parameter Block located via EXE$GL_RPB ; ;-- .ALIGN LONG ; Exception and Interrupt routines must ; be longword aligned ROLL_PFAIL_IS:: ; ; HALT ADDL2 #2,(SP) ; BUMP PC PAST FAULTING INST BICB2 #^X8,7(SP) ; CLEAR FIRST PART DONE BIT MTPR R10,#PR$_KSP ; Restore KSP MOVL R11,^X08(R1) ; Restore interrupt vector MOVL #SS$_NORMAL,R0 ; Assume success PUSHR #^M ; Save all registers MOVL @#EXE$GL_RPB,R5 ; Get address of restart parameter block MOVL RPB$L_IOVEC(R5),R6 ; Calculate the physical address of MOVL @#MMG$GL_SPTBASE,R7 ; the boot driver in the present system EXTZV #9,#21,R6,R8 ; and store for ROLLIN. ASHL #2,R8,R8 ;create offset EXTZV #0,#21,(R7)[R8],R9 ;get PFN ASHL #9,R9,R9 ;convert to address INSV R6,#0,#9,R9 ;add byte offset MOVL R9,RPB_PHY_IOVEC(R5) ;save in RPB ; PUSHR #^M ; SAVE REGISTERS MOVC3 #ROLLINLENGTH,- ; Move ROLLIN code to RPB ROLLIN_PI,- RPB_ROLLIN_CODE(R5) POPR #^M ; RESTORE REGISTERS ; MOVAB @#EXE$GQ_SYSDMP,R4 ;GET ADDRESS OF DESCRIPTOR FOR DUMP FILE ADDL3 (R4),4(R4),R0 ;COMPUTE CHECK SUM BNEQ 5$ ;CONTINUE IF FILE NOT NULL ERROR #SS$_ENDOFFILE 5$: MCOML R0,R0 ;COMPLEMENT CMPL R0,@#EXE$GL_DMPCHK ;COMPARE WITH CHECK SUM BEQL 6$ ;BRANCH IF OK ERROR #SS$_FILACCERR 6$: MOVL (R4)+,R9 ;GET SIZE OF DUMP FILE BGTR 7$ ;BRANCH IF NOT NEG OR ZERO ERROR #SS$_ENDOFFILE 7$: MOVL (R4),R10 ;AND LBN BGTR 8$ ;BRANCH IF CONTIGUOUS ERROR #SS$_FILNOTCNTG 8$: ADDL2 #3,R10 ;SKIP HEADER AND ERRLOGS ; ; PREPARE TO: ; WRITE ALL OF MEMORY STARTING AT 0 TO REMAINDER OF DUMP FILE ; THE ASSUMPTIONS ARE MADE THAT MEMORY EXISTS CONTIGUOUSLY STARTING AT ; PHYSICAL PAGE 0 AND THAT THE SPT WAS LOCATED IN THE HIGHEST PHYSICAL ; PAGES USED. ; CLRL R7 ;SET STARTING ADDRESS MFPR #PR$_SBR,R8 ;PHYSICAL ADDDRESS OF SPT MFPR #PR$_SLR,R0 ;LENGTH OF SPT MOVAL (R8)[R0],R8 ;COMPUTE END OF DUMP SUBL2 #3,R9 ; ACCOUNT FOR HEADER AND 2 ERRLOG BUFFS ASHL #-9,R8,R2 ; CONVERT BYTES TO BLOCKS CMPL R2,R9 ; CHECK FOR FILE BIG ENOUGH BLEQU 10$ ; BRANCH IF OK ERROR #SS$_INSFBUFDP ; ; NOW SAVE THE VOLATILE REGISTERS ; 10$: MFPR #PR$_TODR,@#EXE$GL_PFAILTIM ; Save time of day at power fail MFPR #PR$_PCBB,RPB$L_PCBB(R5); Save physical address of current pcb MFPR #PR$_SCBB,RPB$L_SCBB(R5); Save physical address of System Control Block MFPR #PR$_SBR,RPB$L_SBR(R5) ; Save physical address of System page table MFPR #PR$_SISR,RPB$L_SISR(R5); Save software interrupt summary register MFPR #PR$_SLR,RPB$L_SLR(R5) ; Save SPT length ; ; Save all other volatile processor registers on the current stack (ISP) ; MFPR #PR$_KSP,-(SP) ; Save kernel stack pointer MFPR #PR$_ESP,-(SP) ; Save exec stack pointer MFPR #PR$_SSP,-(SP) ; Save supervisor stack pointer MFPR #PR$_USP,-(SP) ; Save user stack pointer MFPR #PR$_ASTLVL,-(SP) ; Save AST level MFPR #PR$_PME,-(SP) ; Save performance monitor enable MFPR #PR$_P0BR,-(SP) ; Save P0 base register MFPR #PR$_P0LR,-(SP) ; Save P0 length register MFPR #PR$_P1BR,-(SP) ; Save P1 base register MFPR #PR$_P1LR,-(SP) ; Save P1 length register MFPR #PR$_SBIMT,-(SP) ; Save SBI maintenance register .PAGE ; ; All volatile machine state necessary for restart has now been saved. ; At this point the interrupt stack contains: ; ; +-------------------------+ ; | SBIMT | 00(SP) ; +-------------------------+ ; | P1LR | 04(SP) ; +-------------------------+ ; | P1BR | 08(SP) ; +-------------------------+ ; | P0LR | 12(SP) ; +-------------------------+ ; | P0BR | 16(SP) ; +-------------------------+ ; | PME | 20(SP) ; +-------------------------+ ; | ASTLVL | 24(SP) ; +-------------------------+ ; | USP | 28(SP) ; +-------------------------+ ; | SSP | 32(SP) ; +-------------------------+ ; | ESP | 36(SP) ; +-------------------------+ ; | KSP | 40(SP) ; +-------------------------+ ; | R0 | 44(SP) ; +-------------------------+ ; | R1 | 48(SP) ; +-------------------------+ ; | R2 | 52(SP) ; +-------------------------+ ; | R3 | 56(SP) ; +-------------------------+ ; | R4 | 60(SP) ; +-------------------------+ ; | R5 | 64(SP) ; +-------------------------+ ; | R6 | 68(SP) ; +-------------------------+ ; | R7 | 72(SP) ; +-------------------------+ ; | R8 | 76(SP) ; +-------------------------+ ; | R9 | 80(SP) ; +-------------------------+ ; | R10 | 84(SP) ; +-------------------------+ ; | R11 | 88(SP) ; +-------------------------+ ; | AP | 92(SP) ; +-------------------------+ ; | FP | 96(SP) ; +-------------------------+ ; | PC | 100(SP) ; +-------------------------+ ; | PSL | 104(SP) ; +-------------------------+ ; MOVL SP,RPB$L_ISP(R5) ; Save final interrupt stack pointer MOVQ RPB$L_BASE+4(R5),- ; Save 16 bytes of RPB to unused RPB_SAVED_Q1(R5) MOVQ RPB$L_BASE+12(R5),- ; area. RPB_SAVED_Q2(R5) ; ; WAIT 3 SECONDS TO ALLOW ANY OUTSTANDING OPERATION ; ON SYSTEM DEVICE TO COMPLETE ; PUSHR #^M ; SAVE REGISTERS MFPR #PR$_TODR,R0 ; GET CURRENT TIME ADDL2 #300,R0 ; SET 3 SECOND INCREMENT 100$: MFPR #PR$_TODR,R1 ; GET UPDATED TIME CMPL R1,R0 ; CHECK IF WAIT TIME COMPLETE BLSS 100$ ; BRANCH IF WAIT NOT COMPLETE POPR #^M ; RESTORE REGISTERS ; ; NOW DUMP ALL OF CORE TO THE SYSDUMP FILE ; ; MOVL R2,AP ;SAVE NO. OF BLOCKS TO WRITE BSBW WRITEDUMP ;DUMP IT BLBS R0,WAIT ; BRANCH IF NO ERRORS ADDL2 #44,SP ; UNWIND STACK CLRL @#EXE$GL_PFAILTIM ; UNDO PFAIL INDICATOR ERROR ; DECLARE ERROR AND RETURN PRESENT R0 .PSECT YROLLD MESSAGE1: .ASCIC \ (HEX) PAGES OF MEMORY SAVED.\ MESSAGE: .ASCIC \%ROLLOUT-I-SUCCESS SYSTEM ROLLOUT COMPLETE \ MESSEND:: .PSECT YROLL WAIT: ; DECLARE SUCCESS CLRL R11 ; SET FOR CONSOL IO BSBW EXE$OUTCRLF ; CARRIAGE RETURN,LF MOVAL MESSAGE,R1 BSBW EXE$OUTCSTRING MOVL AP,R1 ;GET NUMBER OF PAGES SAVED BSBW EXE$OUTHEX MOVAL MESSAGE1,R1 BSBW EXE$OUTCSTRING BSBW EXE$OUTCRLF LOOP: BRB LOOP ;WAIT FOR CONSOLE HALT .PAGE .SBTTL WRITEDUMP - WRITE DATA TO DUMP FILE ; ; WRITE DATA TO SYSTEM DUMP FILE ; ; INPUTS: ; R5 - ADDRESS OF RESTART PARAMETER BLOCK ; R6 - ADDRESS OF BOOTDRIVER VECTOR ; R7 - BUFFER ADDRESS ; R8 - SIZE OF BUFFER IN BYTES ; R9 - SIZE OF DUMP FILE IN BLOCKS ; R10 - LBN OF DUMP FILE (UPDATED) ; ; OUTPUTS: ; R7 - UPDATED ; R8 - UPDATED ; R9 - UPDATED ; R10 - UPDATED ; IOSIZE=127*512 ;MAXIMUM TRANSFER SIZE WRITEDUMP: ; MOVZWL #IOSIZE,R3 ;ASSUME MAXIMUM CMPL R3,R8 ;CHECK AGAINST REQUESTED SIZE BLEQ 10$ ;LESS THAN TOTAL REQUEST MOVL R8,R3 ;ELSE LIMIT TO REQUEST SIZE 10$: MOVAB 511(R3),R2 ;ROUND TRANSFER SIZE TO PAGE BOUND ASHL #-9,R2,R2 ;AND CONVERT TO PAGE COUNT CMPL R2,R9 ;CHECK FOR OVER END OF FILE BLEQ 20$ ;CONTINUE IF NOT MOVL #SS$_INSFBUFDP,R0 ;SET ERROR CODE RSB ;RETURN WITH ERROR 20$: PUSHL R5 ;SET ADDRESS OF RPB EXTZV #VA$V_SYSTEM,#1,R7,-(SP);USE SYSTEM BIT AS VIRTUAL FLAG PUSHL S^#IO$_WRITELBLK ;SET FUNCTION CODE PUSHL R10 ;LBN IN DUMP FILE PUSHL R3 ;SIZE OF BUFFER IN BYTES PUSHL R7 ;ADDRESS OF BUFFER CALLS #6,@(R6)[R6] ;CALL BOOTDRIVER BLBS R0,25$ ;CHECK FOR ERROR RSB ;RETURN IF ERROR 25$: ADDL R3,R7 ;UPDATE BUFFER ADDRESS ADDL R2,R10 ;UPDATE LBN SUBL R2,R9 ;AND SIZE OF FILE BLEQ 30$ ;DONE IF END OF FILE SUBL R3,R8 ;UPDATE BYTE COUNT BGTR WRITEDUMP ;RECYCLE IF NOT COMPLETE 30$: RSB ; .PAGE .SBTTL ROLLIN_PI - POSITION INDEPENDENT ROLLIN CODE .PSECT ZROLL,LONG,PIC,SHR,NOWRT ;++ ; ; Functional Description: ; ROLLIN_PI is entered from the ROLLIN Secondary Bootstrap ; routine. ; The code is located in the unused portion of the RPB. ; Objective is to restore all physical memory starting at ; location ^X200 by calling the device independent QIO ; routine BOO$QIO. ; ; Enviornment: ; Mode=Kernal, Menory Management OFF ; IS=1, IPL=31 ; ; Assumptions: ; Machine configuration has not changed, (memory configuration, ; disks, etc.); and thus the device independent boot driver was ; located at the same physical address that it resided in the ROLLEDOUT ; system. During restoration of physical memory, this driver ; code is assumed to overlay itself!! ; ; Calling Sequence: ; JMP RPB_ROLLIN_CODE+4-^X200(SP) ; ; Input Parameters: ; R5 - Address of Bootdriver vector (physical) ; R6 - Buffer address in physical memory (updated) ; R7 - Volatile ; R8 - Logical Block number in file SYSDUMP.DMP (updated) ; R9 - Blocks remaining in file (updated) ; R11 - Base of RPB ; SP - Address of RPB+^X200 ; PR$_SCBB- Base of RPB (routine uses an abbreviated SCB) ; ; Implicit Inputs: ; NONE ; ; Output Parameters: ; AP - RESTRT_POWERUP = 3 (indicates to EXE$RESTART that powerfail occured. ; ; Memory layout at start of ROLLIN_PI ; ; +-----------------------------------------+ :BASE ; ! First Longword of RPB ! ; +-----------------------------------------+ :BASE+4 ; ! ROLLIN SCB values point to HALT ! ; +-----------------------------------------+ :BASE+20 ; ! ! ; ! Restart Parameter Block (RPB) ! ; ! ! ; +-----------------------------------------+ :BASE+RBP$K_LENGTH ; ! ! ; ! Saved :BASE+4 to :BASE+20 ! ; ! ! ; +-----------------------------------------+ :BASE+RPB$K_LENGTH+16 ; ! ! ; ! Physical address of Bootdriver in ! ; ! saved system image ! ; ! ! ; +-----------------------------------------+ :BASE+RPB$K_LENGTH+20 ; ! ! ; ! HALT Instruction for possible ! ; ! Machine Check ! ; ! ! ; +-----------------------------------------+ :BASE+RPB$K_LENGTH+24 ; ! ! ; ! ROLLIN Code ! ; ! ! ; +-----------------------------------------+ ; ! ! ; ! ROLLIN STACK ! ; ! ! ; +-----------------------------------------+ :BASE+^X200 ; ! ! ; ! Primary Bootstrap Code ! ; ! ! ; ! ! ; +-----------------------------------------+ :PR$_SCBB ; ! ! ; ! System Control Block ! ; ! ! ; +-----------------------------------------+ :PFNMAP ; ! ! ; ! PFN Bitmap ! ; ! ! ; +-----------------------------------------+ :PFNMAP+^X800 ; ! ! ; ! Bootstrap Stack ! ; ! ! ; +-----------------------------------------+ :(SP) ; ! ! ; ! Secondary Bootstrap Code ! ; ! ! ; +-----------------------------------------+ ; ; Equated Symbols IOSIZE = 127 ; Max size of BOO$QIO transfer ; 64KB ; .ALIGN LONG ROLLIN_PI:: HALT ; Service for machine checks .ALIGN LONG 20$: MOVZBL #IOSIZE,R7 ; Assume maximum transfer CMPL R7,R9 ; Minimize with file size BLEQ 30$ ; Smaller than remaining file size MOVL R9,R7 ; Set to remaining file size 30$: PUSHL R11 ; Base of RPB PUSHL #0 ; Set mode to physical PUSHL #IO$_READLBLK ; Set function to read PUSHL R8 ; Set Logical Block Number ROTL #9,R7,-(SP) ; Set transfer size in bytes PUSHL R6 ; Set buffer address ADDL 4(SP),R6 ; Update buffer address ADDL R7,R8 ; and block number CALLS #6,@(R5)[R5] ; Call bootdriver BLBS R0,40$ ; Branch if no errors HALT ; Neat error handling, huh? 40$: SUBL R7,R9 ; Decrement blocks remaining BGTR 20$ ; Another transfer if not done MTPR RPB$L_SCBB(R11),#PR$_SCBB ; Set SCBB into restored system MOVQ RPB_SAVED_Q1(R11),- ; Restore displaced RPB values. RPB$L_BASE+4(R11) MOVQ RPB_SAVED_Q2(R11),- ; RPB$L_BASE+12(R11) MOVL #RESTRT_POWERUP,AP ; Set up AP for EXE$RESTART JMP @RPB$L_RESTART-^X200(SP); JUMP TO EXE$RESTART ROLLINLENGTH=.-ROLLIN_PI ; .END