Trailing-Edge
-
PDP-10 Archives
-
bb-bt99h-bb
-
klser.x14
There are 3 other files named klser.x14 in the archive. Click here to see a list.
TITLE KLSER - KL10 PROCESSOR DEPENDENT CODE - FROM KISER V176 -V562
SUBTTL J.M. FLEMMING/JMF & D.A. LEWINE/DAL/EVS 20 MAY 86
SEARCH F,S,DTEPRM
$RELOC
$HIGH
;THIS SOFTWARE IS FURNISHED UNDER A LICENSE AND MAY ONLY BE USED
; OR COPIED IN ACCORDANCE WITH THE TERMS OF SUCH LICENSE.
;
.CPYRT<1973,1986>
;COPYRIGHT (C) 1973,1974,1975,1976,1977,1978,1979,1980,1982,1984,1986
;BY DIGITAL EQUIPMENT CORP., MAYNARD, MASS.
;ALL RIGHTS RESERVED.
;
XP VKLSER,562 ; PUT VERSION NUMBER IN GLOB LISTING AND LOADER STORAGE MAP
ENTRY KLSER ;LOAD KLSER IF LIBRARY SEARCH
KLSER::
SUBTTL TRAP HANDLING AND CONTEXT SWITCHING
;HERE TO PROCESS USER ARITHMETIC OVERFLOW TRAPS
SAROVF::
DMOVE T1,.USMUO ;GET PC DBL WRD
MOVE T3,.JDAT+JOBENB## ;GET USER'S ENABLE BITS
TRNN T3,AP.AOV ;OVERFLOW - IS THE USER ENABLED?
TLNE T1,(XC.FOV) ;TRAP CAUSED BY FOV?
CAIA ;YES,
JRST SAROV6 ;NOT ENABLED, IGNORE IT
HRRI T3,AP.AOV+AP.FOV;ASSUME FLOATING OVERFLOW
TLNN T1,(XC.FOV) ;WAS IT A FLOATING OVERFLOW TRAP?
TRZ T3,AP.FOV ;NO, INTEGER OVERFLOW
;HERE WITH T1,T2=PC, T3=APRENB BITS
SAROV3: TLNE T2,MXSECN ;IN A NON-ZERO SECTION?
JRST SAROV9 ;CAN'T TRAP IT THIS WAY THEN
REPEAT 0,<
TLZ T1,637 ;CLEAR NON-EX BITS (KA COMPATABILITY)
>
HLLM T1,.JDAT+JOBTPC## ;SAVE OLD PC
HRRM T2,.JDAT+JOBTPC## ;..
MOVEM T3,.JDAT+JOBCNI## ;LIKE CONI ON THE KA-10
MOVE T3,.JDAT+JOBENB## ;GET USER'S ENABLE BITS
TRNE T3,XP.DDU ;USER WANT TRAPS REENABLED?
JRST SAROV5 ;YES, LEAVE AS IS
HLLZS .JDAT+JOBENB## ;CLEAR USER'S ENABLE BITS SO MUST DO APRENB AGAIN
MOVSI T3,(JFCL) ;NOP
MOVEM T3,.USAOT ;IGNORE ARITHMETIC TRAPS
MOVEI T3,UP.PDT
MOVEM T3,.USPDT ;EXEC WILL FIELD PDL OVERFLOWS
SETZM .CPCN1## ;CLEAR POSSIBLE NXM OR CLOCK ENABLES
SAROV5: MOVEI T3,XP.CLK ;ALWAYS DISABLE CLOCK
ANDCAM T3,.CPCN1##
HRRZ T3,.JDAT+JOBAPR## ;PC IN TRAP ROUTINE?
CAIE T3,0(T2)
CAIN T3,-1(T2)
JRST SAROV7 ;YES
HRR T2,.JDAT+JOBAPR## ;GET USER'S TRAP ADDRESS
TLZ T1,(XC.OVF+XC.FOV+XC.FUF+XC.NDV+IC.BIS+IC.AFI)
TLO T1,(XC.PUB!XC.USR) ;INSURE PUBLIC AND USER MODE IS SET
SAROV6: DMOVEM T1,.USMUO ;NEW PC WITH TRAP CAUSING BITS CLEARED
MOVE P,[XWD MJOBPD##,.JDAT+JOBPDL##] ;SET UP A STACK
PUSHJ P,SCDCHK## ;CHECK IF WE SHOULD RESCHEDULE
USERAC ;SET USER AC BLOCK
XJRSTF .USMUO ;EXIT TO THE USER'S TRAP HANDLER
SAROV7: MOVEI T3,XP.LTH ;STUCK IN LOOP BIT
SAROV9: DMOVEM T1,.CPAPC## ;SAVE OLD PC FOR ERROR MESSAGE
HRRM T3,.CPAEF##
JRST SEPDL3
;HERE TO PROCESS EXEC STACK OVERFLOW TRAPS
SEPDLO::EXCH T1,.USMUP ;GET THE PC
MOVEM T1,.CPAPC##+1 ;STORE PC
HLLZ T1,.USMUO ;FLAGS
MOVEM T1,.CPAPC## ;SET AS ERROR FLAGS FOR ERRCON
TLNN T1,(XC.USR) ;WAS THIS IN USER MODE?
JRST DOPDL ;NOPE, EXEC, SOMETHING'S WRONG, CRASH
HRRI T1,AP.POV ;SET PUSH DOWN OVERFLOW FLAG
SEPDL1: HRRM T1,.CPAEF## ;IN .CPAEF SO ERRCON WILL GET CALLED
MOVE T1,.USMUP ;RESTORE T1
SEPDL3: SETOM .CPSCF## ;SET FORCED RESCHEDULING FLAG
SETOM .CPCKF## ;AND CLOCK FLAG
CONO PI,CLKBIT##+PI.IIO ;REQUEST A CLOCK INTERRUPT
JRST . ;WAIT UNTIL CLOCK LEVEL HAPPENS AND THE JOB
; IS STOPPED IN USER MODE.
DOPDL:: EXCH T1,.USMUP ;SAVE PC AND RESTORE T1
MOVEM P,@.CPEPL## ;SAVE OLD P
HRRZS P ;SEE IF
CAMLE P,SYSSIZ## ;UUO OR INTERRUPT LEVEL
XJRST [MCSEC1+EXTPDL##] ;UUO, TRY TO EXTEND THE PDL
JRST EPOSTP## ;CAN'T RECOVER ON INTERRUPT LEVEL
;HERE TO PROCESS PAGE FAILURE TRAPS
SEILM:: CONI PI,.CPTPI## ;SAVE THE PI STATE
CONSO PI,PI.ON ;IS THE PI SYSTEM ON?
JRST SEIL2 ;NO--PROCESS TRAP IMMEDIATELY
CONSZ PI,@.CPACO## ;APR CHANNEL ON?
CONSZ PI,@.CPAPP## ;YES--DID THIS TRAP HAPPEN AT CPU PI LEVEL?
JRST SEIL1 ;YES--PROCESS TRAP IMMEDIATELY
CONSZ APR,LP.PAR!LP.NXM ;NO--IS AN MB PARITY OR NXM INTERRUPT COMING?
JRST .-1 ;YES--LET IT RUN AND THEN CONTINUE THE TRAP
SEIL1:: CONO PI,PI.OFF ;NOW INSURE THAT PI'S ARE OFF
SEIL2: DATAI PAG,.CPTCX## ;SAVE THE TRAP CONTEXT
EXECAC ;WANT MONITOR'S AC BLOCK
JRSTF @[IC.UOU+.+1] ;INSURE USRIOT IS ON SO PXCT WORKS
MOVEM T1,.CPSTT## ;SAVE T1 TEMPORARILY
LDB T1,[POINT 5,.USPFW,5] ;PICK UP PF CODE
CAIL T1,20 ;IS THIS A REAL PAGE FAULT
CAIN T1,PF.ABF ; OR AN ADDRESS BREAK?
JRST SEILMA ;YES--GO PROCESS IT
CAIN T1,PF.IID ;IS IT AN ILLEGAL INDIRECT ADDRESS?
JRST SEILMA ;YES--GO PROCESS IT
CAIE T1,PF.ISN ;IS IT AN ILLEGAL SECTION NUMBER?
CAIN T1,PF.PRV ;IS IT A PROPRIETARY VIOLATION?
JRST SEILMA ;YES--GO PROCESS
CAIL T1,PF.ARP ;IS IT A PARITY TRAP?
JRST PRTRP ;YES--GO PROCESS
CAIN T1,PF.PTP ;IS IT PAGE TABLE PARITY?
JRST PTPAR ;YES--GO PROCESS
CAIN T1,PF.PRF ;IS IT A PAGE REFILL FAILURE?
STOPCD (.,CPU,PRF) ;++PAGE REFILL FAILURE
STOPCD (.,CPU,IPC) ;++ILLEGAL PAGE FAILURE TRAP CODE
;HERE ON AR OR ARX PARITY TRAP (PAGE FAIL CODE 36 OR 37)
PRTRP:
IFN FTMP,<
CONSZ PI,@.CPAPP## ;APR PI IN PROGRESS?
JRST PRTRPA ;YES, DIE INTERLOCK IS ALREADY OWNED
DIELOK ;NO, GRAB THE DIE INTERLOCK
PRTRPA:>
SKIPE .CPPSP## ;CORE SWEEP IN PROGRESS?
JRST SWTRP ;YES, JUST SAVE LOCATION OF FAILURE AND DISMISS
MOVEI T1,@.CPEBR## ;NORMAL EBR
TRZ T1,LG.CSW ;TURN OFF CACHE LOAD BIT
CONO PAG,(T1) ;TURN OFF CACHE LOAD AND CLEAR PAGE TABLE
MOVE T1,.CPSTT## ;RESTORE T1
MOVEM 17,.CPA17## ;SAVE AC 17
MOVEI 17,.CPA00## ;MAKE BLT POINTER
BLT 17,.CPA17##-1 ;SAVE AC'S IN CPU DATA BLOCK
MOVE P,.CPEPD## ;SET UP ERROR STACK
PUSHJ P,CPUSTS## ;READ CPU STATUS
PUSHJ P,DVCSTS## ; AND DEVICE STATUS
MOVE J,.CPJOB## ;SET UP J WITH CURRENT JOB RUNNING
MOVE T1,JBTPPN##(J) ;GET ITS PPN
MOVEM T1,.CPEJN## ; AND SAVE IT
MOVE T1,JBTNAM##(J) ;GET ITS PROGRAM NAME
MOVEM T1,.CPEPN## ; AND SAVE IT
AOS .CPNPT## ;COUNT TOTAL NUMBER OF AR/ARX PARITY TRAPS
DMOVE T1,.USPFP ;GET THE PAGE FAIL PC
DMOVEM T1,.CPMDP## ;FOR ERROR IN JOB MESSAGES
DMOVEM T1,.CPPPD## ;STORE TROUBLE PC
TDZ T1,[7777,,-1] ;HOKEY IT UP
IOR T1,T2 ;SINCE A ONE WORD GETTAB
MOVEM T1,.CPPPC## ;SAVE THE PC FOR DAEMON
MOVEM T1,.CPMPP## ;ALSO OLD PLACE
MOVE T3,.USPFW ;GET THE PAGE FAIL WORD
MOVEM T3,.CPPFW## ;SAVE THE PAGE FAIL WORD FOR DAEMON
LDB T4,[POINT 5,T3,5] ;GET THE PAGE FAIL CODE
SUBI T4,PF.ARP ;CONVERT TO INDEX INTO AC BLOCK 7
DATAO PAG,[LG.LAB+7B11] ;SET PREVIOUS ACS TO BLOCK 7
PXCT PX.MEM,[MOVE T4,(T4)] ;PICK UP BAD DATA WORD FROM BLOCK 7
EXECAC ;RESTORE MONITOR AC SETTINGS
MOVEM T4,.CPTBD## ;SAVE BAD DATA FOR DAEMON
TLNE T1,(XC.USR) ;IS THE TRAP FROM EXEC MODE?
JRST PRTRPC ;NO--CONTINUE
SKIPE .CPCHE## ;IS TRAP FROM CHANNEL ERROR REPORTING?
JRST PRTCHN ;YES--SPECIAL HANDLING
TLZ T2,777740 ;GET JUST THE ADDRESS OF OFFENDING INSTRUCTION
TLZ T3,777740 ;GET JUST THE ADDRESS OF OFFENDING REFERENCE
CAMN T2,T3 ;IS AN INSTRUCTION FETCH AT FAULT?
JRST PRTRPC ;YES--CONTINUE
MOVE T1,(T2) ;NO--PICK UP THE OFFENDING INSTRUCTION
TLNN T1,740 ;IS THE AC FIELD NON-ZERO?
JRST PRTRPC ;NO--CONTINUE
LSH T1,-^D27 ;YES--GET JUST THE OP CODE
CAIE T1,256 ;IS THIS A PXCT THEN?
JRST PRTRPC ;NO--CONTINUE
MOVE T1,(T2) ;YES, GET THE PXCT BACK
TLZ T2,-1 ;ONLY 18 BITS
TLNN T1,37 ;SAFE TO FETCH THE OPERAND?
CAIN T2,(T1)
JRST PRTRP9 ;NO, NONE OF THESE ARE BLTS ANYWAYS
LDB T3,[POINT 9,(T1),8] ;GET OP-CODE OF PXCT'ED INSTRUCTION
CAIE T3,(BLT/1000) ;IS IT A BLT?
JRST PRTRP9 ;NO
TLNN T1,PX.SRC*40 ;BLT FROM USER TO EXEC?
JRST PRTRPC ;NO, EXEC TO USER
PRTRP9: MOVSI T3,(PF.USR) ;YES--GET THE USER REFERENCE BIT
IORB T3,.CPPFW## ; AND FIX THE PAGE FAIL WORD (HARDWARE IS WRONG)
JRST PRTRP1 ;REFERENCE WAS VIRTUAL
;THE CODE BETWEEN HERE AND PRTRP2 IS AN ELABORATE NOOP SINCE THE MICROCODE
; DOES NOT INDICATE A PHYSICAL REFERENCE IN THE PAGE FAIL WORD EVEN IF THE
; PARITY ERROR OCCURRED AS A RESULT OF THE MICROCODE MAKING A PHYSICAL REFERENCE.
; IT'S INCLUDED IN CASE THE MICROCODE GETS FIXED
; ACTUALLY, THE MICROCODE SHOULDN'T BE BLAMED SINCE ITS A HARDWARE BUG
PRTRPC: MOVE P1,.CPPFW## ;GET THE PAGE FAIL WORD
MOVE T3,.CPMAP## ;GET .EPMP FOR THIS CPU
PUSH P,.ERPIL/PAGSIZ##(T3)
; TLNE P1,(PF.PHY) ;A PHYSICAL REFERENCE?
; JRST PRTRP1 ;NO, CALCULATE PHYSICAL FROM VIRTUAL ADDRESS
;HERE TO PRETEND PF.PHY WAS ON AND REFERENCE POSSIBLE PHYSICAL LOCATIONS
TLZ P1,777760 ;ISOLATE PHYSICAL ADDRESS
CAILE P1,777 ;COULD THE REFERENCE HAVE BEEN TO A PAGE MAP?
JRST PRTRP0 ;NO, THEN P1 IS THE REAL PHYSICAL ADDRESS
;IF THE PAGE FAIL WORD IS LESS THAN 777, THE REFERENCE COULD HAVE BEEN
; AN EPT OR UPT RELATIVE PHYSICAL REFERENCE MADE BY THE MICROCODE. TRY
; REFERENCING THAT LOCATION IN THE APPROPRIATE MAP TO SEE IF BAD PARITY
SKIPL .CPPFW## ;REFERENCE TO THE EXEC ADDRESS SPACE?
CONI PAG,P1 ;YES, GET THE PAGE NUMBER OF THE EPT
SKIPGE .CPPFW## ;OR A REFERENCE TO USER ADDRESS SPACE?
DATAI PAG,P1 ;YES, GET THE PAGE NUMBER OF THE UPT
ANDI P1,17777 ;ISOLATE THE PAGE NUMBER
LSH P1,P2WLSH## ;PHYSICAL ADDRESS OF THE MAP
IOR P1,.CPPFW## ;PHYSICAL ADDRESS OF REFERENCE
TLZ P1,777760 ;CLEAR CRUFT
PUSHJ P,TRYREF ;TRY REFERENCING THE LOCATION IN THE MAP
JRST PRTRP2 ;FAILED, STORE IT
JRST PRTRP1 ;DIDN'T FAIL, ASSUME REFERENCE TO USER OR EXEC
; PAGE 0
;EVEN THOUGH NOT A REFERENCE TO PAGE 0, STILL COULD BE A PHYSICAL REFERENCE (SPT,CST)
PRTRP0: PUSHJ P,TRYREF ;SEE IF BAD PARITY IN PHYSICAL LOCATION
JRST PRTRP2 ;YES, STORE PHYSICAL ADDRESS
;HERE IF WE BELIEVE THAT THE ADDRESS IN THE PAGE FAIL WORD IS REALLY A
; VIRTUAL ADDRESS. MUST BE TRUE OR THE PARITY ERROR WAS SPURIOUS
PRTRP1: MOVE T4,[PXCT PX.MEM,[MAP P1,(P1)]] ;SET UP PXCT OF MAP INSTRUCTION
SKIPL .CPPFW## ;IS THIS A USER CONTEXT REFERENCE?
TLZ T4,(PX.MEM,) ;NO--THEN PXCT BECOMES REGULAR XCT
MOVE P1,.CPPFW## ;NOT PHYSICAL REFERENCE, GET VIRTUAL ADDRESS
XCT T4 ;DO A MAP TO TURN PF WORD INTO PHYS ADDR IN P1
PRTRP2: MOVEM P1,.CPPBA## ;SAVE BAD PHYSICAL ADDR FOR DAEMON
TLZ P1,777760 ;GET RID OF LEFT HALF STUFF
ROT P1,W2PLSH## ;TURN RH OF P1 INTO PAGE NUMBER OF BAD LOC
PUSHJ P,MAPREF ;SETUP MAPPING FOR RETRY REFERENCES
LSH P1,-^D27 ;TURN P1 INTO WORD NUMBER WITHIN PAGE
ADDI P1,.ERPIL ;AND GET PAGE NUMBER CORRESPONDING TO MAP SLOT
MOVEI T1,[ASCIZ . AR/ARX parity trap.]
PUSHJ P,PRMPC ;ANNOUNCE ERROR
MOVEI T1,[ASCIZ /Page fail word = /]
MOVE T2,.CPPFW##
PUSHJ P,PRMHW ;PRINT THE PAGE FAIL WORD
MOVEI T1,[ASCIZ /Mapped page fail address = /]
MOVE T2,.CPPBA##
PUSHJ P,PRMHW ;PRINT THE MAP WORD (PHYS. ADDRESS)
MOVEI T1,[ASCIZ /Incorrect contents = /]
MOVE T2,.CPTBD##
PUSHJ P,PRMHW ;PRINT THE BAD DATA
MOVEI T1,[ASCIZ /CONI PI, = /]
MOVE T2,.CPTPI##
PUSHJ P,PRMHW ;PRINT THE CONI PI BITS
SETZ P2, ;CLEAR FLAG REGISTER
CONSO PAG,LG.CSL ;IS THE CACHE ON?
JRST PRTRP3 ;NO
TRO P2,PFCPF3 ;REMEMBER IT'S IN USE
SWPVA ;SWEEP WRITTEN ENTRIES BACK TO MEMORY
CONSO APR,LP.CSD ;SWEEP BUSY?
JRST .-1 ;WAIT FOR DONE
MOVE T1,.CPAPI## ;GET APR PIA
CONO APR,LP.CSF!LP.CSD(T1) ;CLEAR CACHE SWEEP DONE
CONSO APR,LP.PAR ;MB PARITY DURING SWEEP?
JRST PRTRP3 ;NO--START RETRIES
TRO P2,PFCPF4 ;YES--REMEMBER THIS PROBLEM
MOVEI T1,[ASCIZ /MB parity error occurred during cache sweep prior to retry attempt.
ERA = /]
RDERA T2 ;PICK UP THE ERA
PUSHJ P,PRMHW ;PRINT MESSAGE AND ERA
PUSHJ P,CLRSBD## ;CLEAR MEMORY CONTROLLERS
MOVE T1,.CPAPI## ;GET APR PIA
CONO APR,LP.CSF!LP.SBE!LP.PAR(T1) ;CLEAR THE APR
;HERE TO START RETRIES-FIRST WITH CACHE OFF
PRTRP3: MOVE T1,.CPPBA## ;BAD PHYSICAL ADDRESS
TLZ T1,777760 ;CLEAR LEFT HALF JUNK
LSH T1,W2PLSH## ;CONVERT TO PAGE NUMBER
IDIVI T1,^D36 ;INDEX INTO NXM TABLE
MOVE T2,BITTBL##(T2) ;BIT IN NXM TABLE
TDNE T2,NXMTAB##(T1) ;PAGE ALREADY KNOWN TO BE IN NON-EXISTANT MEMORY?
JRST [SETZ P1,
JRST PRHMX] ;DON'T REFERENCE NON-EXISTANT MEMORY
MOVEI T1,@.CPEBR## ;GET NORMAL CONO PAG, BITS
TRZ T1,LG.CSW!LG.CSL ;TURN OFF LOOK AND LOAD
CONO PAG,(T1) ;MAKE SURE CACHE IS OFF
PUSHJ P,PRTRY ;REFERENCE LOCATION WITHOUT CACHE
JRST PRHMF ;RETRIES FAILED! HARD MEMORY FAILURE
;HERE WE KNOW WE CAN RECOVER THE USER
MOVEM T1,.CPTGD## ;SAVE THE GOOD DATA FOR ERROR REPORTING
AOS .CPSAR## ;UPDATE COUNTER OF SOFT AR/ARX PARITY ERRORS
HRRM T3,.CPPTR## ;STORE RETRY COUNT
TRNN P2,PFCPF3 ;WAS CACHE ON WHEN WE STARTED?
JRST PRTRP5 ;NO--GO FINISH UP
;HERE RESTORE GOOD DATA TO THE CACHE LOCATION
MOVEI W,@.CPEBR## ;GET NORMAL EBR
MOVE U,W ;2ND COPY
TRZ U,LG.CSW ;TURN OFF LOAD IN THIS ONE
MOVE S,T1 ;SETUP GOOD DATA TO WRITE TO CACHE
MOVE T1,[CONO PAG,(W)] ;TURN ON CACHE LOOK & LOAD
MOVE T2,[MOVEM S,(P1)] ;REWRITE GOOD DATA TO CACHE
MOVE T3,[CONO PAG,(U)] ;TURN OFF CACHE LOAD
MOVE T4,[JRST PRTRP4] ;GET BACK TO THIS CODE
JRST T1 ;EXECUTE THE INSTRUCTIONS IN THE AC'S
;SO THEY DON'T GET INTO POSSIBLY BAD CACHE
;NOW RETRY REFERENCE WITH CACHE ON, CACHE STILL HAS LOOK BIT ON BUT LOAD OFF
PRTRP4: PUSHJ P,PRTRY ;REFERENCE LOCATION
JRST PRHCF ;RETRIES FAILED! HARD CACHE FAILURE
SWPIA ;INVALIDATE CACHE BUT DON'T TOUCH CORE
CONSO APR,LP.CSD ;SWEEP BUSY?
JRST .-1 ;WAIT FOR DONE
MOVE T1,.CPAPI## ;GET APR PIA
CONO APR,LP.CSF!LP.CSD(T1) ;CLEAR CACHE SWEEP DONE
CONO PAG,@.CPEBR## ;TURN ON CACHE LOOK & LOAD
;HERE IF RETRIES WERE SUCCESFUL, LOG SOFT ERROR AND DISMISS
PRTRP5: HRLM P2,.CPPTR## ;SAVE STATUS FLAGS FOR ERROR REPORTING
DPB T3,[POINT 9,.CPPTR##,26] ;PUT CACHE RETRY COUNT HERE
MOVE T3,.CPMAP## ;GET .EPMP FOR THIS CPU
POP P,.ERPIL/PAGSIZ##(T3)
PUSHJ P,CLRSBD## ;CLEAR MEMORY CONTROLLERS
MOVE T1,.CPAPI## ;GET APR PIA
CONO APR,LP.CSF!LP.SBE!LP.PAR(T1) ;CLEAR ANY APR ERRORS
MOVEI T1,[ASCIZ /Retry successful! Correct contents = /]
MOVE T2,.CPTGD
PUSHJ P,PRMHW ;PRINT SUCCESS AND GOOD DATA
MOVEI T1,EDELIM## ;GET ADDRESS OF TEXT
PUSHJ P,PRMSG ;PRINT END DELIMITER
PUSHJ P,DAELOG ;LOG THE ERROR
JRST PTXIT ;EXIT THE TRAP
;LOCAL ROUTINE TO SETUP A MAP SLOT TO MAKE PHYSICAL REFERENCES
;RETURNS +1 ALWAYS
;PRESERVES LEFT HALF OF P1, CLOBBERS RIGHT HALF
MAPREF: MOVE T3,.CPMAP## ;GET PAGE NUMBER OF EPMP FOR THIS CPU
HRRM P1,.ERPIL/PAGSIZ##(T3)
HRRI P1,(<PM.DCD>B2+PM.WRT+PM.PUB)
HRLM P1,.ERPIL/PAGSIZ##(T3)
CLRPGT (0,.ERPIL) ;CLEAR OUT OLD ENTRY FOR .ERPIL
POPJ P, ;RETURN
;LOCAL ROUTINE TO REFERENCE A PHYSICAL ADDRESS
;ENTER WITH P1 = PHYSICAL ADDRESS TO BE REFERENCED
;RETURNS +1 IF LOCATION CONTAINS BAD PARITY
;RETURNS +2 IF CONTENTS OK
TRYREF: PUSHJ P,SAVE1## ;SAVE PHYSICAL ADDRESS
LSH P1,W2PLSH## ;PAGE TO MAP
PUSHJ P,MAPREF ;SETUP MAPPING TO REFERENCE PHYSICAL ADDRESS
MOVE P1,-1(P) ;GET BACK PHYSICAL ADDRESS
ANDI P1,PG.BDY## ;WORD NUMBER WITHIN THE PAGE
ADDI P1,.ERPIL ;VIRTUAL ADDRESS OF WORD TO TRY
; PJRST PRTRY ;REFERENCE THE WORD AND SEE IF IT CONTAINS BAD PARITY
;LOCAL RETRY ROUTINE
;RETURNS +1 IF RETRIES FAIL
;RETRUNS +2 IF ANY RETRY WINS
; T1/GOOD DATA
; T3/RETRY WHICH SUCCEEDED (FIRST =1)
PRTRY: MOVEI T3,1 ;INIT RETRY COUNTER
MOVEI T2,TRYBAD ;GET TEST TRAP ADDRESS
EXCH T2,.USPFN+1 ;EXCHANGE WITH WHAT'S THERE NOW
PUSH P,.USPFP ;IF A TRAP HAPPENS, HOW WE GOT HERE IS LOST
PUSH P,.USPFP+1 ;SECOND HALF
PRTY1: TRO P2,PFCPF0 ;NOTE THIS IS TEST REFERENCE
MOVE T1,0(P1) ;TRY THE REFERENCE
TRZ P2,PFCPF0 ;CLEAR THE REFERENCE FLAG
TRZN P2,PFCPF2 ;ERROR DURING REFERENCE?
JRST PRTY3 ;NO--GIVE A GOOD RETURN
CAIGE T3,TRPTRY ;YES--RETRY COUNT EXHAUSTED?
AOJA T3,PRTY1 ;NO--TRY AGAIN
SKIPA ;YES--GIVE AN ERROR RETURN
PRTY3: AOS -2(P) ;SET FOR SKIP RETURN
POP P,.USPFP+1 ;AND SECOND WORD
POP P,.USPFP ;RESTORE OLD CONTENTS
EXCH T2,.USPFN+1 ;RESTORE STANDARD TRAP ADDRESS
POPJ P, ;EXIT
;HERE ON TRAPS OCCURING DURING RECOVERY ATTEMPTS
TRYBAD: TRNN P2,PFCPF0 ;ARE WE HERE BECAUSE OF TEST REFERENCE?
STOPCD (.,HALT,UPF) ;++UNEXPECTED PAGE FAIL
LDB T1,[POINT 5,.USPFW,5] ;GET PAGE FAIL CODE
CAIE T1,PF.ARP ;AR PARITY ERROR?
STOPCD (.,HALT,WPT) ;++WRONG PARITY TRAP
TRO P2,PFCPF2 ;YES--INDICATE ERROR
AOS .USPFP+1 ;RETURN TO TEST REFERENCE + 1
XJRSTF .USPFP ;RETURN
;CACHE HAS LOOK ON BUT NOT LOAD
;HERE IF CACHE RETRIES FAIL WE MAY TURN OFF CACHE NOW
PRHCF: SWPIA ;INVALIDATE CACHE BUT DON'T TOUCH CORE
CONSO APR,LP.CSD ;SWEEP BUSY?
JRST .-1 ;WAIT FOR DONE
MOVE T1,.CPAPI## ;GET APR PIA
CONO APR,LP.CSF!LP.CSD(T1) ;CLEAR CACHE SWEEP DONE
MOVEI T1,@.CPEBR## ;INITIAL EBR
TRZ T1,LG.CSL!LG.CSW ;TURN OFF THE LOOK BIT FOR SAFETY
CONO PAG,(T1) ;MAY LEAVE IT OFF
TRO P2,PFCPF2 ;SET THE CACHE FAILED BIT FOR ERROR REPORTING
AOS T1,.CPCEC## ;COUNT THIS FAILURE
CAIGE T1,CCHEMX ;EXCEEDED ALLOWABLE?
JRST PRHC1 ;NO-TURN IT BACK ON
MOVEI T1,[ASCIZ /Three non-recoverable cache parity errors
have occurred since processor started.
CACHE HAS BEEN TURNED OFF./]
PUSHJ P,PRMSG ;ANNOUNCE CACHE DESELECT
MOVEI T1,LG.CSL!LG.CSW;TURN OFF LOOK & LOAD BITS
ANDCAM T1,.CPEBR## ;BITS NOW CLEARED SO OTHERS
;CAN'T TURN IT ON BY ACCIDENT
TRO P2,PFCPF5 ;SET CACHE DESELECTED FLAG FOR ERROR REPORTING
JRST PRTRP5 ;NOW CLEAN UP AND RETURN TO USER
;HERE TO TURN THE CACHE BACK ON
PRHC1: CONO PAG,@.CPEBR## ;TURN IT ON
JRST PRTRP5 ;AND RETURN TO USER
;HERE WHEN RETRIES FROM MEMORY FAIL
PRHMF: SETZM (P1) ;ZERO (AND RE-WRITE) THE ROTTEN LOCATION ALSO
PUSH P,P2 ;SAVE P2
PUSH P,T3 ;SAVE T3
PUSHJ P,PRTRY ;NOW SEE IF IT'S REALLY HARD (MEMORY BROKEN)
TDZA P1,P1 ;IT IS, SET P1 = 0
SETO P1, ;IT'S NOT, SET P1 = -1
POP P,T3 ;RESTORE T3
POP P,P2 ;RESTORE P2
PRHMX: SETZM .CPTGD## ;ZERO "GOOD DATA" SINCE WE DIDN'T GET ANY
MOVE T1,.CPMAP## ;GET .EPMP FOR THIS CPU
POP P,.ERPIL/PAGSIZ##(T1)
AOS .CPHPT## ;BUMP HARD (AR/ARX) PARITY TRAP COUNT
SWPIA ;INVALIDATE CACHE BUT DON'T TOUCH CORE
CONSO APR,LP.CSD ;SWEEP BUSY?
JRST .-1 ;WAIT FOR DONE
PUSHJ P,CLRSBD## ;CLEAR MEMORY CONTROLLERS
MOVE T1,.CPAPI## ;GET APR PIA
CONO APR,LP.CSF!LP.SBE!LP.PAR!LP.CSD(T1) ;CLEAR THE APR
TRO P2,PFCPF1 ;SAY HARD ERROR FOR ERROR REPORTING
HRLM P2,.CPPTR## ;SAVE FLAGS
HRRM T3,.CPPTR## ;SAVE RETRY COUNT FOR ERROR REPORTING
CONO PAG,@.CPEBR## ;TURN THE CACHE BACK ON
MOVEI T1,[ASCIZ /Retries unsuccessful. Offending location zeroed./]
PUSHJ P,PRMSG ;ANNOUNCE FAILURE
PUSHJ P,DAELOG ;CALL DAEMON TO LOG THE ERROR
MOVE T1,.CPPPC## ;GET THE TRAP PC
TLNE T1,(XC.USR) ;IS THE TRAP FROM USER MODE?
JRST PRHMF1 ;YES--GO KILL USER
HRRZ T1,.CPPFW## ;GET THE PROBLEM ADDRESS
SKIPGE .CPPFW## ;IS THIS A USER CONTEXT REFERENCE?
JRST PRHMF0 ;YES--GO CHECK IF AT SCHED OR PI LEVEL
MOVE T2,SYSLEN## ;NO--GET LENGTH OF MONITOR'S HIGH SEG
ADDI T2,MONORG##-1 ;FORM EVA OF THE TOP OF THE HIGH SEG
CAIL T1,MONORG## ;IS THE ERROR IN THE
CAILE T1,(T2) ; MONITOR'S HIGH SEGMENT?
JRST PRHMF0 ;NO--GO CHECK OTHER THINGS
LSH T1,W2PLSH## ;YES--FORM THE EXEC VIRTUAL PAGE NUMBER
MOVE T2,.CPPBA## ;GET THE MAPPED PHYSICAL ADDRESS
TDZ T2,[777760,,777] ;ONLY WANT BASE ADDRESS OF PAGE
PUSHJ P,PAGRPL## ;TRY TO REPLACE THIS CODE PAGE
JRST PARHLT## ;IT DIDN'T WORK
MOVEI T1,[ASCIZ /Replaced monitor code page from disk./] ;GET TEXT
PUSHJ P,PRMSG ;PRINT IT
MOVEI T1,EDELIM## ;GET END DELIMITER
PUSHJ P,PRMSG ;PRINT IT
PJRST PTXIT ;EXIT THE TRAP
PRHMF0: SETOM .CPREP## ;SET PARITY MSG FLAG IN CASE THIS IS FATAL
SKIPN .CPISF## ;ARE WE IN THE SCHEDULER
CONSZ PI,PI.IPA ; OR ARE WE AT INTERRUPT LEVEL?
JRST PARHLT## ;YES--SORRY BUT WE CAN'T DO A THING
SKIPGE .CPPFW## ;WAS THIS A MONITOR REF TO USER SPACE AT UUO LVL?
JRST PRHMF2 ;YES--TREAT AS USER ERROR
CAIL T1,FYSORG ;NO--IS THE ERROR IN THE
CAILE T1,.LPPP-1 ; USER PER PROCESS AREA?
JRST PARHLT## ;NO--IT'S IN THE MONITOR DATA BASE, FATAL!
SETZ P2, ;YES, CALL IT A LOWSEG ERROR
JRST PRHMF3 ;TREAT AS FATAL USER ERROR
PRHMF1: MOVEI T1,UE.PEF ;GET PARITY ERROR BIT
TDNN T1,.CPCN1## ;IS USER ENABLED TO HANDLE THIS HIMSELF?
JRST PRHMF2 ;NO--GO ON
MOVE T2,JBTSTS##(J) ;YES--GET JOB STATUS WORD
TLNE T2,JACCT ;IS JOB PRIVILEGED?
JRST PRHF1A ;YES--TRAP TO HIM
MOVE T2,JBTPPN##(J) ;NO--GET HIS PPN
CAME T2,FFAPPN## ;IS IT THE OPERATOR PPN
CAMN T2,UMDPPN## ; OR THE USER MODE DIAG PPN?
JRST PRHF1A ;YES--LET'S TRAP TO HIM AS REQUESTED
JRST PRHMF2 ;NO--THEN WE IGNORE HIS TRAP REQUEST
PRHF1A: MOVEI T1,EDELIM## ;GET END DELIMITER
PUSHJ P,PRMSG ;PRINT IT
IFN FTMP,<
CONSO PI,@.CPAPP## ;APR PI IN PROGRESS?
JRST [DIENLK ;NO, RETURN THE DIE INTERLOCK
JRST .+1]
>
CONO PI,PI.ON ;TURN PI'S BACK ON
DMOVE T1,.CPPPD## ;GET THE PROBLEM PC
MOVEI T3,UE.PEF ;PARITY ERROR
JRST SAROV3 ;GO TRAP TO USER
PRHMF2: SETZ P2, ;SET FLAG ASSUMING LOW SEG ERROR
MOVE J,.CPJOB## ;GET THE OFFENDING JOB #
SKIPG J,JBTSGN##(J) ;DOES THIS JOB HAVE A HIGH SEG?
JRST PRHMF3 ;NO--GO ON
HRRZ T1,.CPPFW## ;GET THE PROBLEM ADDRESS
CAML T1,.USHSS ;IS ADDRESS IN THE USER HIGH SEGMENT?
CAMLE T1,.USHSE
JRST PRHMF3 ;NO--GO ON
SETO P2, ;YES--SET FLAG INDICATING HIGH SEG ERROR
PUSHJ P,HGHPAR## ;GO PROCESS JOBS USING THIS SEGMENT
PRHMF3: JUMPN P1,PRHMF4 ;IF MEMORY IS OK, DON'T MARK OUT PAGE
LDB T1,[POINT 13,.CPPBA##,26] ;GET THE PAGE NUMBER TO MARK OFF-LINE
PUSH P,T1 ;SAVE PAGE NUMBER
IDIVI T1,^D36 ;COMPUTE NXMTAB INDEX AND BITTBL INDEX
MOVE T2,BITTBL##(T2) ;GET CORRECT BIT TO SET
TDNE T2,NXMTAB##(T1) ;ALREADY A NON-EXISTANT PAGE?
JRST PRHMF4 ;YES, COULD HAPPEN IF REFERENCE TO A NON-EXISTANT ADDRESS
IORM T2,NXMTAB##(T1) ;MARK OUT PAGE IN NXMTAB
MOVEI T1,[ASCIZ /Location still bad after zeroing.
Setting off-line physical page /] ;GET TEXT
POP P,T2 ; AND PAGE NUMBER
PUSHJ P,PRMOC ;TELL HIM WHAT WE DID
MOVE T1,[.CSCPO,,.ERCSC]
PUSHJ P,DAEDIE## ;LOG CONFIGURATION CHANGE
PRHMF4: MOVEI T1,EDELIM## ;GET END DELIMITER
PUSHJ P,PRMSG ;PRINT IT
MOVE J,.CPJOB## ;GET JOB NUMBER
JUMPE P2,PRHMF5 ;GO STOP THIS JOB IF LOW SEG ERROR
MOVEI T1,JS.MPE ;DID HGHPAR SAY THAT THIS JOB
TDNE T1,JBTSTS##(J) ; COULDN'T BE SAVED?
JRST PRHMF5 ;YES--JUST GO STOP IT
IFN FTMP,<
CONSO PI,@.CPAPP## ;APR PI IN PROGRESS?
JRST [DIENLK ;NO, RETURN THE DIE INTERLOCK
JRST .+1]
>
CONO PI,PI.ON ;TURN THE PI'S BACK ON
MOVE P,[XWD MJOBPD##,.JDAT+JOBPDL##] ;DUMMY STACK FOR WSCHED
PUSH P,.USPFP ;STACK RETURN USER ADDRESS FOR WSCHED
PUSH P,.USPFP+1 ;SECOND HALF AS WELL
PJRST WSCHED## ;RESCHEDULE THIS JOB TO RE-RUN WITH NEW HI SEG
PRHMF5: PUSHJ P,PARJB1## ;CLEAR JACCT AND SET JS.MPE
MOVSI T1,(CP.PXX) ;GET PRINT REQUEST BIT
TRO T1,UE.PEF ;ALSO FLAG PARITY ERROR
IORM T1,.CPAEF## ;SET REQUEST FOR PI 7
SETOM .CPSCF## ;FORCE RESCHEDULE
SETOM .CPCKF## ;SET FLAG FOR PI 7 INTERRUPT
IFN FTMP,<
CONSO PI,@.CPAPP## ;APR PI IN PROGRESS?
JRST [DIENLK ;NO, RETURN THE DIE INTERLOCK
JRST .+1]
>
CONO PI,XI.RQC## ;REQUEST PI 7
CONO PI,PI.ON ;ALLOW INTERRUPTS NOW (MAINLY PI 7)
PJRST ESTOP## ;GO STOP THIS JOB
;HERE ON TRAP DURING PARITY SWEEP
SWTRP: EXCH T1,.CPSTT## ;RESTORE T1, SAVE TRAP CODE
PUSH P,T1 ;SAVE T1
HRRZ T1,.USPFP+1 ;GET PC OF TRAP
CAIE T1,CPLMPI ;BETTER MATCH THE SWEEP BLT ADDRESS
STOPCD (.,HALT,NPI) ;++NOT PARITY INSTRUCTION
MOVE T1,.USPFW ;GET THE PAGE FAIL WORD
MOVEM T1,.CPPFW## ;AND SAVE IT
MOVE T1,.CPAER## ;GET ERA FROM INTERRUPT THAT SHOULD HAVE HAPPENED
MOVEM T1,.CPSTE## ;SAVE AS ERA CORRESPONDING TO THIS SWEEP TRAP
MOVE T1,.CPSTT## ;GET PAGE FAIL CODE
SUBI T1,PF.ARP ;CONVERT TO INDEX INTO AC BLOCK 7
DATAO PAG,[LG.LAB+07B11] ;SET PREVIOUS AC BLOCK TO 7
PXCT PX.MEM,[MOVE T1,(T1)] ;GET BAD DATA WORD FOR DAEMON
EXECAC ;RESTORE MONITOR'S AC BLOCK
MOVEM T1,.CPTBD## ;SAVE BAD DATA
SETOM .CPPTH## ;INDICATE ERROR ON SWEEP
MOVEI T1,3 ;BUMP RETURN PC BY 3 TO
ADDM T1,.USPFP+1 ; INDICATE A TRAP HAPPENED
POP P,T1 ;RESTORE T1
JRST PTXIT1 ;EXIT BACK TO SWEEP ROUTINE
;HERE ON TRAPS FROM CHANNEL ERROR REPORTING CODE
;NOTE: P3 IS THE AC USED IN THE CHANNEL ERROR CODE TO ACCESS DATA IN CORE
PRTCHN: CONO PAG,@.CPEBR## ;RESTORE CACHE SETTINGS
DATAO PAG,.CPTCX## ;SET AC BLOCK TO ONE IN USE AT TIME OF TRAP
MOVE P3,.CPTBD## ;PUT ACCESSED DATA (THOUGH BAD) IN P3
EXECAC ;BACK TO MONITOR AC SETTINGS
AOS .USPFP+1 ;BUMP RETURN PC OVER MOVE INSTRUCTION
JRST PTXIT ;EXIT THE TRAP
;ROUTINE TO PRINT A MESSAGE PREFIXED BY "CPUx" AND
;FOLLOWED BY "AT EXEC(USER) PC XXXXXX"
; T1=MESSAGE ADDRESS
PRMPC: PUSHJ P,SAVE1## ;SAVE P1 TO REMEMBER ADDRESS OF MESSAGE
MOVE P1,T1 ;SAVE
PUSHJ P,SVPPC## ;SWITCH TO SECONDARY PROTOCOL
PUSH P,.CPTOA## ;SAVE COMMAND OUTPUT ADDRESS
MOVEI T2,CTYWAT## ;GET ONE THAT DOESN'T USE PI SYS
MOVEM T2,.CPTOA##
MOVEI T1,SDELIM## ;GET ADDRESS OF TEXT
PUSHJ P,CONMES## ;PRINT START DELIMITER
MOVE T2,.CPLOG## ;GET THIS CPU'S NAME
PUSHJ P,PRNAME## ;PRINT IT
MOVE T1,P1 ;GET ADDRESS OF MESSAGE IN T1
PUSHJ P,CONMES## ;PRINT MESSAGE
DMOVE T1,.CPPPD## ;GET SAVED PC
PUSHJ P,DPCP## ;PRINT "AT EXEC/USER XXXXXX"
MOVEI T1,[ASCIZ / on /] ;SEPARATE FROM DATE/TIME
PUSHJ P,CONMES## ;PRINT IT
PUSHJ P,DAYTIM## ;PRINT DATE AND TIME
MOVEI T1,[ASCIZ /Job/];TELL THEM WHO WAS RUNNING
PUSHJ P,CONMES## ;PRINT "JOB"
PUSHJ P,PRJBNM## ;PRINT JOB INFO
MOVEI T1,[ASCIZ / was running
/]
PUSHJ P,CONMES## ;PRINT "WAS RUNNING"
PRMPC2: POP P,.CPTOA## ;RESTORE SCNSER ADDRESS
POPJ P, ;RETURN
;ROUTINES TO PRINT A MESSAGE FOLLOWED BY NUMBER IN HALFWORD OR OCTAL FORMAT
; T1=MESSAGE ADDRESS, T2=NUMBER
PRMOC: PUSHJ P,SAVE3## ;SAVE P1-P3
MOVEI P3,OCTPNT## ;GET ADDRESS OF OCTAL PRINT ROUTINE
JRST PRMHW1 ;GO TO COMMON CODE
PRMHW: PUSHJ P,SAVE3## ;SAVE P1-P3
MOVEI P3,HWDPNT## ;GET ADDRESS OF HALFWORD PRINT ROUTINE
PRMHW1: MOVE P1,T1 ;SAVE
MOVE P2,T2 ;SAVE
PUSHJ P,SVPPC## ;SWITCH TO SECONDARY PROTOCOL
PUSH P,.CPTOA## ;SAVE COMMAND OUTPUT ADDRESS
MOVEI T2,CTYWAT## ;GET ONE THAT DOESN'T USE PI SYS
MOVEM T2,.CPTOA##
MOVE T1,P1 ;GET ADDRESS OF MESSAGE IN T1
PUSHJ P,CONMES## ;PRINT MESSAGE
MOVE T1,P2 ;GET NUMBER TO PRINT (IF ANY)
PUSHJ P,(P3) ;PRINT NUMBER IN DESIRED FORMAT
PUSHJ P,CRLF## ;END WITH CRLF
PJRST PRMPC2 ;FINISH UP
;ROUTINE TO PRINT A MESSAGE
; T1=MESSAGE ADDRESS
PRMSG: PUSHJ P,SAVE2## ;SAVE P1,P2 TO REMEMBER ADDRESS OF MESSAGE
MOVE P1,T1 ;SAVE
PUSHJ P,SVPPC## ;SWITCH TO SECONDARY PROTOCOL
PUSH P,.CPTOA## ;SAVE COMMAND OUTPUT ADDRESS
MOVEI T2,CTYWAT## ;GET ONE THAT DOESN'T USE PI SYS
MOVEM T2,.CPTOA##
MOVE T1,P1 ;GET ADDRESS OF MESSAGE IN T1
PUSHJ P,CONMES## ;PRINT MESSAGE
PUSHJ P,CRLF## ;END WITH CRLF
PJRST PRMPC2 ;FINISH UP
;ROUTINE TO LOG AN ERROR + CPU AND DEVICE STATUS BLOCKS
DAELOG: MOVEI T1,.ERKPT ;CODE FOR DAEMON
HRL T1,.CPSLF## ;THIS CPU'S CDB ADDRESS
PUSHJ P,DAEDIE## ;PUT THE ENTRY IN THE QUEUE
PJRST RCDSTD## ;ALSO, QUEUE ENTRY FOR CPU AND DEVICE STATUS BLOCK
;HERE ON PAGE TABLE PARITY TRAP (PF CODE 25)
PTPAR: DIELOK ;GRAB THE DIE INTERLOCK
CONO PAG,@.CPEBR## ;CLEAR THE PAGE TABLE
AOS .CPPTP## ;COUNT A PAGE TABLE PARITY ERROR
MOVE T1,.CPSTT## ;RESTORE T1
MOVEM T1,.CPA17## ;SAVE 17
MOVEI 17,.CPA00## ;MAKE BLT POINTER
BLT 17,.CPA17##-1 ;SAVE ACS IN CPU DATA BLOCK
MOVE P,.CPEPD## ;SET UP ERROR STACK
SKIPGE T1,.CPPTF## ;PICK UP COUNT OF PAGE TABLE FAILURES
MOVEI T1,^D4 ;NONE YET, INITIALIZE FOR 3 RETRIES
SOJG T1,PTPAR1 ;IF COUNT HASN'T EXPIRED, JUST RETRY.
; COUNTER IS RESET ON EVERY CLOCK TICK.
MOVE J,.CPJOB## ;CURRENT JOB
MOVE T1,.CPPPD## ;PC
TLNE T1,(XC.USR) ;IN USER MODE?
JRST PRHMF5 ;YES, JUST ZAP THE JOB
DIENLK ;UNLOCK SO CAN CALL DIE
STOPCD .,CPU,PGTPAR, ;++PAGE TABLE PARITY
PTPAR1: MOVEM T1,.CPPTF## ;REMEMBER COUNTER
DMOVE T1,.USPFP ;GET PAGE FAIL PC
DMOVEM T1,.CPPPD## ;SAVE FOR PRINT ROUTINE
MOVE J,.CPJOB## ;SET UP J WITH CURRENTLY RUNNING JOB
MOVEI T1,[ASCIZ / page table parity trap/]
PUSHJ P,PRMPC ;ANNOUNCE ERROR
MOVEI T1,[ASCIZ /Page fail word = /]
MOVE T2,.USPFW
MOVEM T2,.CPPFW## ;FOR CRASH
PUSHJ P,PRMHW ;PRINT THE PAGE FAIL WORD
MOVEI T1,[ASCIZ /CONI PI, = /]
MOVE T2,.CPTPI##
PUSHJ P,PRMHW ;PRINT THE CONI PI BITS
MOVEI T1,EDELIM## ;GET ADDRESS OF TEXT
PUSHJ P,PRMSG ;PRINT END DELIMITER
PTXIT: MOVSI 17,.CPA00## ;BLT POINTER TO RESTORE ACS
BLT 17,16 ;RESTORE ACS
MOVE 17,.CPA17## ;AC 17 ALSO
PTXIT1: DATAO PAG,.CPTCX## ;RESTORE THE CONTEXT AT TIME OF TRAP
IFN FTMP,<
CONSO PI,@.CPAPP## ;APR PI IN PROGRESS?
JRST [DIENLK ;NO, RETURN THE DIE INTERLOCK
JRST .+1]
>
EXCH T1,.CPTPI## ;GET PI'S AT TRAP ENTRY, SAVE T1
TRNE T1,PI.ON ;WERE THE PI'S ON?
CONO PI,PI.ON ;YES--TURN PI'S BACK ON
EXCH T1,.CPTPI## ;RESTORE T1
XJRSTF .USPFP ;RESTORE FLAGS AND RETURN
;HERE ON REAL PAGE FAULTS OR ADDRESS BREAKS
SEILMA: MOVE T1,.CPSTT## ;RESTORE T1
CONO PI,PI.ON ;TURN PI SYSTEM BACK ON
SKIPN .CPEJ1## ;SKIP NEXT IF EXEC PAGE FAULT IN PROGRESS
DMOVEM T1,.CPST1## ;SAVE T1 AND T2 IN CASE OF CRASH
DMOVE T1,.USPFP ;GET THE PAGE FAIL PC
DMOVEM T1,.CPAPC## ;STORE IT AS POTENTIAL ERROR PC
DMOVEM T1,.USMUP ;STORE WHERE KI WOULD PUT IT
HRR T1,T2 ;GET PC INTO T1 AS A ONE WORD PC
MOVE T2,.USPFW ;GET THE USER PAGE FAIL WORD
MOVEM T2,.CPPFW## ;SAVE PAGE FAULT WORD FOR CRASH
SEILMB: TLNE T1,(XC.USR) ;PAGE FAULT IN EXEC MODE?
JRST SEILM0 ;NO, PROCEED
LDB T2,[POINT 5,T2,5] ;CLEAR ALL BUT THE PAGE FAIL CODE
CAIN T2,PF.ABF ;WAS THE PAGE FAULT AN ADDRESS BREAK?
JRST SEILM1 ;YES, REMEMBER IT AND GO AWAY
JRST SEILM7 ;NO, EXEC ILL MEM REF, LOOK FOR ERJMP
SEILM0: MOVE P,[XWD MJOBPD##,.JDAT+JOBPDL##] ;SETUP A PUSH DOWN LIST
SKIPN .USJOB
STOPCD .,CPU,PFN ;++PAGE FAULT IN NULL JOB
PUSH P,.USPFP+1 ;SAVE USER'S PC
MOVE T3,T2 ;FAULT WAS IN USER MODE, SAVE PFC FOR
; POSSIBLE CALL TO USRFLT
LDB T2,[POINT 5,T2,5] ;CLEAR ALL BUT THE PAGE FAIL CODE
CAIN T2,PF.ABF ;ADDRESS BREAK?
JRST SEILM1 ;YES, GO PROCESS
MOVE T4,.JDAT+JOBENB## ;GET APR ENABLE BITS
TRNE T4,AP.ILM ;IS USER ENABLED?
JRST SUILM ;YES--DO SUILM INSTEAD
HRRI T1,AP.ILM ;ILLEGAL MEMORY REFERENCE
CAIN T2,PF.ISN ;ILLEGAL SECTION?
JRST SEPDL1 ;YES
CAIN T2,PF.PRV ;WAS IT A PROPRIETARY VIOLATION?
JRST [TRO T1,AP.PPV ;INDICATE PROP VIO
JRST SEPDL1]
DMOVE T1,.USPFP ;GET DOUBLE WORD PC
PUSHJ P,USRFLT## ;SEE IF PAGE FAULT FOR A VM USER
; WILL NOT RETURN IF SO (DISPATCH TO USER)
HRRI T1,AP.ILM ;COULDN'T HANDLE IT - USER GETS ILL MEM REF
JRST SEPDL1 ;GO SAY "ILL. MEM. REF."
SEILM1: DMOVE T1,.USPFP ;GET FAULT DOUBLE WORD PC
TLO T1,(IC.AFI) ;INHIBIT ADDRESS BREAK WHEN INSTRUCTION IS EXECUTED
DMOVEM T1,.CPPC## ;STASH WHERE PSISER CAN FIND IT
EXCH J,.CPJOB## ;GET JOB
PUSH P,W ;SAVE W IN CASE IN EXEC MODE
PUSHJ P,FNDPDS## ;FIND THE PDB
LDB T2,[POINT 9,.PDTMI##(W),17] ;GET THE PROCEED COUNT
SOSL T2 ;DECREMENT
DPB T2,[POINT 9,.PDTMI##(W),17] ;STORE IT BACK IF POSITIVE
POP P,W ;RESTORE W
JUMPG T2,SEILM3 ;CONTINUATION PC
;DON'T BREAK IF PROCEED COUNT .GT. 0
MOVE T2,JBTSTS##(J) ;IS THIS A JACCT
TLNN T2,JACCT ;JOB
JRST SEILM6 ;NOT JACCT
MOVE T2,JBTPPN##(J) ;YES, BUT IS
CAME T2,FFAPPN## ; HE GOD?
JRST SEILM3 ;NO-IGNORE BREAK
SEILM6: EXCH J,.CPJOB## ;UNDO LAST EXCH
TLNN T1,(XC.USR) ;PC IN USER MODE?
JRST SEILM2 ;NO, REMEMBER BREAK AND GO AWAY
MOVEM T1,.JDAT+JOBPD1## ;SAVE FLAGS
PUSH P,.CPPC##+1 ;AND PC
MOVE R,.CPADR## ;SETUP R
IFN FTPI,<
MOVE J,.CPJOB## ;JOB NUMBER FOR PSISER
SIGNAL C$ADRB ;SIGNAL THAT AN ADDRESS BREAK HAS OCCURED
JRST .+2 ;USER DOESN'T WANT TRAP
JRST SEILM5 ;INTERRUPT TO THE USER
> ;END FTPI
PUSHJ P,TTYFUW## ;FIND THE USER'S TTY
PUSHJ P,INLMES## ;REPORT THE ADDRESS BREAK
ASCIZ /
%Address break/
DMOVE T1,.JDAT+JOBPD1## ;GET THE USER'S PC
PUSHJ P,DPCP## ;TELL HIM WHERE THE BREAK OCCURED
IFN FTPI,<
PUSHJ P,PSIERR## ;PENDING INTERRUPT?
JFCL
PJRST ERRGOU## ;YES, GIVE IT TO THE USER
>
SEILMD: DMOVE T1,.JDAT+JOBPD1## ;GET USERS PC
DMOVEM T1,.CPPC## ;COULD HAVE CHANGED IF WE HAD TO WAIT
PUSHJ P,HOLD0## ;STOP THE JOB IN A CONTINUABLE STATE
PJRST WSCHD3##
SEILM2: MOVEI T2,JS.ASA ;AC'S ARE IN THE SHADOW AREA BIT
EXCH J,.CPJOB## ;JOB NUMBER
TDNE T2,JBTSTS##(J) ;SAVE/GET IN PROGRESS?
JRST SEILM3 ;YES, DON'T BOTHER THE USER WITH BREAKS ON THAT
MOVEI T2,JS.ABP ;ADDRESS BREAK HAPPENED DURING UUO PROCESSING BIT
IORM T2,JBTST2##(J) ;REMEMBER THAT THE BREAK HAPPENED
SEILM3: EXCH J,.CPJOB## ;RESTORE J
SEILM4: MOVE T1,.CPPC## ;GET FLAGS OF PC
TLNE T1,(XC.USR) ;BREAK OUT OF USER MODE?
JRST SEILM5 ;YES
DMOVE T1,.CPST1## ;RESTORE T1 AND T2
XJRSTF .CPPC## ;GO AWAY AND TELL THE USER ABOUT THE BREAK
; AT UUO EXIT
SEILM5: USERAC ;USER'S AC BLOCK
XJRSTF .CPPC## ;EXIT TO USER
;HERE IF AN ILL MEM REF OCCURED IN EXEC MODE, CHECK FOR ERJMP OR
;ERCAL BEFORE CALLING IT AN IME
SEILM7: CONSO PI,PI.IPA ;AT INTERRUPT LEVEL?
JRST SEJLM2 ;NO, UUO LEVEL, OK
CONSO PI,PI.IPA-PI.IP7 ;YES - LEVEL 7?
SKIPN .CPISF## ;YES, FROM SCHEDULER?
JRST SEILME ;PI1 - PI6 OR NON-SCHEDULER PI7
SEJLM2: SKIPE .CPEJ1## ;NESTING?
JRST @[0,,SEILM8] ;YES, IT'S AN IME
MOVE T2,.CPPFW## ;GET FULL PAGE FAULT WORD
IFN FTPEEKSPY,<
JUMPG T2,SEJL2A ;JUMP IF NOT USER REF
PUSHJ P,INTLVL## ;YES, AT UUO LEVEL?
PUSHJ P,[PUSHJ P,SAVT## ;YES, SAVE VOLATILE ACS
MOVE T1,T2 ;VIRTUAL ADDRESS
LSH T1,W2PLSH## ;PAGE NUMBER
ANDI T1,HLGPGS
MOVE T4,T1 ;PAGE #
LSH T4,P2SLSH## ;ISOLATE SECTION #
SKIPE .UPMP+SECTAB(T4) ;IF SECTION NXS, NOT SPY
PUSHJ P,TSSPT## ;FAULT ON A SPY PAGE?
POPJ P, ;NO
PJRST UADERR##] ;YES, BLAME THE USER
SEJL2A:>
DMOVEM T1,.CPEJ1## ;"TOP LEVEL", REMEMBER IN CASE WE NEST
DMOVEM T1,.CPEJ3## ;ALSO SAVE HERE FOR PSYCHOPATHIC CASES
MOVE T2,.USPFP+1 ;GET PC FAULT OCCURRED AT
TLNE T2,-1 ;NON-ZERO SECTION?
XJRST [MCSEC1+.+1] ;GO INTO SECTION 1
LDB T1,[POINT 22,T2,35] ;GET ADDRESS PART OF PAGE FAIL WORD
SKIP (T1) ;TOUCH PAGE FAULT PC LOCATION AND
LDB T2,[POINT 13,1(T1),12] ;GET INSTRUCTION FOLLOWING
; IF THE PC JUMPED OFF INTO THE BOONIES
; THEN THIS WILL PAGE FAULT AND WE WILL
; KNOW WE HAVE A REAL IME
CAIE T2,<ERJMP>_-^D23 ;IS IT AN ERJMP?
JRST SEILM8 ;NO, THEN WE HAVE AN IME
MOVE T2,1(T1) ;GET ENTIRE ERJMP EXPRESSION
MOVEM T2,.CPEJ4## ;SAVE WHERE WE CAN FIND IT
TLNN T1,-1 ;NON ZERO SECTION?
JRST SEJLM3 ;NO, DO SECTION 0 CALCULATION
TLZ T2,777740 ;NON-ADDRESSING PART OF ERJMP
TLO T2,(IFIW) ;MAKE A USABLE INDIRECT
XMOVEI T1,@T2 ;RESOLVE ADDRESS OF ERJMP
SKIPA ;JOIN COMMON CODE
SEJLM3: MOVEI T1,@.CPEJ4## ;RESOLVE ADDRESS OF ERJMP
; IF THIS IME'S (NOTE .CPEJ1 STILL
; NON-ZERO) THEN .CPEJ3 HAS ORIGINAL
; TRAP PC WHICH STARTED THIS MESS.
MOVEM T1,.CPAPC##+1 ;SET CONTINUATION ADDRESS
DMOVE T1,.CPST1## ;RESTORE T1&T2
SETZM .CPEJ1## ;CLEAR NESTING FLAG
DATAO PAG,.CPTCX## ;RESTORE TRAP CONTEXT
XJRSTF .CPAPC## ;....
;HERE ON NESTED IME, "RESTORE" THE FIRST IME AND STOPCD
SEILM8: DMOVE T1,.CPEJ1## ;PAGE FAULT PC AND REASON WORDS
MOVEM T1,.CPAPC## ;SET TRUE ERROR PC
MOVEM T1,.USPFP ;ALSO MAKE UPMP LOOK RIGHT
MOVEM T2,.CPPFW## ;SET TRUE PAGE FAULT WORD
MOVEM T2,.USPFW ;ALSO MAKE UPMP LOOK RIGHT
SEILME: SETZM .CPEJ1## ;CLEAR NESTING FLAG
STOPCD .+1,JOB,IME,DIEIME, ;++ILL MEM REF FROM EXEC
DMOVE T1,.USPFW ;GET PAGE FAULT WORD
DMOVEM T1,.CPPC## ;STASH AS CONTINUATION ADDRESS
JRST SEILM4 ;AND CONTINUE
DIEIME: PUSHJ P,INLMES## ;ADD SOME TEXT
ASCIZ /Page fail word = /
MOVE T1,.USPFW ;GET PAGE FAIL WORD
PJRST HWDPNT## ;PRINT AS HALF-WORDS AND RETURN
EXCABK::ANDCAM T1,JBTST2##(J) ;CLEAR BREAK HAPPENED IN EXEC MODE BIT
PUSHJ P,FNDPDS## ;FIND THIS JOB'S PDB
MOVSI T1,(OC.BCM) ;BREAK ON MUUO REFERENCES BIT
TDNN T1,.PDABS##(W) ;IS THE USER INTERESTED?
POPJ P, ;NO, GO AWAY
IFN FTPI,<
DMOVE T1,.JDAT+JOBPD1## ;GET UUO PC
DMOVEM T1,.CPPC## ;STORE IT WHERE PSISER EXPECTS IT
SIGNAL C$ADRB ;SIGNAL THAT AN ADDRESS BREAK OCCURED
SKIPA ;USER DOESN'T WANT TRAP
POPJ P, ;USER IS ENABLED, UUO EXIT WILL INTERRUPT TO HIM
>
PUSHJ P,TTYFUW## ;FIND THE USER'S TTY
PUSHJ P,INLMES## ;REPORT THE ADDRESS BREAK
ASCIZ /
%Address break/
DMOVE T1,.CPAPC##
PUSHJ P,DPCP## ;TELL HIM THAT
MOVEI T1,[ASCIZ/; UUO/]
PUSHJ P,CONMES##
DMOVE T1,.JDAT+JOBPD1## ;GET THE UUO PC
PUSHJ P,DPCP## ;REPORT IT SO HE WILL KNOW WHAT UUO BROKE
IFN FTPI,<
PUSHJ P,PSIERR## ;PENDING INTERRUPT?
JFCL
POPJ P, ;YES
>
POP P,(P) ;POP OFF THE PUSHJ TO EXCABK
JRST SEILMD ;AND STOP THE JOB IN A CONTINUABLE STATE
;HERE FROM SEILM IF PAGE FAULT IS IN USER MODE AND APRENB DONE
;T3=PAGE FAULT WORD
SUILMX::
DMOVE T1,.USMUO ;GET PC FROM "UUO"
JRST SUILM1
SUILM: DMOVE T1,.USPFP ;GET DOUBLE WORD PC
SUILM1: MOVE R,.CPADR## ;GET THE ADDRESS OF THE USER'S JOB DATA AREA
PUSHJ P,USRFLT## ;SEE IF PAGE FAULT FOR VM USER
; WILL NOT RETURN IF SO (DISPATCH TO PFH)
MOVEI T3,AP.ILM ;SET ILM BIT FOR USER
JRST SAROV3 ;FINISH UP
SUPDLO::
DMOVE T1,.USMUO ;GET FLAGS & PC
MOVEI T3,AP.POV ;SET POV BIT FOR USER
JRST SAROV3 ;FINISH UP
;ROUTINE TO SET HARDWARE AND SOFTWARE RELOCATION INFORMATION FOR CURRENT USER
;CALLING SEQUENCE:
; PUSHJ P,SETREL
; ... RETURN HERE
;J = CURRENT JOB NUMBER
;R = PROTECTION,,RELOCATION FOR THE LOW SEGMENT
SETRLH::MOVE J,.CPJOB## ;J=CURRENT JOB NUMBER
MOVEI T1,0
DPB T1,JBYHSS## ;FORCE MAP TO BE REDONE
SETREL::MOVE J,.CPJOB## ;J = CURRENT JOB NUMBER
SETRL1::MOVE R,JBTADR##(J) ;R = XWD PROTECTION,,EXEC VIRTUAL ADDRESS
; OF THE FIRST PAGE OF THE LOW SEGMENT
MOVE T2,.CPADR## ;PREVIOUS JOB'S CORE, 0 IF NONE
MOVEM R,.CPADR## ;SET .CPADR FOR QUICK ACCESS AT APR LEVEL
HLRZM R,.CPREL## ;SET .CPREL FOR ADDRESS CHECKING
IFN FTTRPSET,<
SKIPE T1,.CPSTS## ;HAS TIMESHARING BEEN STOPPED VIA TRPSET?
CAIE T1,(J) ;YES, WAS IT THIS JOB?
JUMPN T1,SETRLZ ;NO, DON'T CHANGE THE UBR
>
SKIPE J ;NULL JOB ALWAYS HAS A UPMP
JUMPE R,SETRLZ ;THERE IS NO UPMP IF THE JOB HAS NO CORE
HRRZ T1,JBTUPM##(J) ;PAGE NUMBER OF THE CURRENT JOB'S UPMP
JUMPE T1,SETRL2 ;DON'T CHANGE ANYTHING IF THERE ISN'T ONE
HRLI T1,(LG.LUB+LG.LPC+LG.KPM) ;SET THE LOAD BIT, PCS = 0
IFN FTRTTRP,<
MOVEM T1,.CPDTO## ;SAVE FOR RTTRP INTERRUPT LEVEL USE
>
CONO PI,PI.OFF ;MAKE CHANGING ADDRESSABILITY ATOMIC
HRRM T1,@.CPSPT##
SKIPN T2 ;LAST JOB STILL HAVE CORE?
DATAO PAG,NULDOP## ;DUMP THE METERS
DATAO PAG,T1 ;SETUP THE UBR, UPDATE METERS
CONO PI,PI.ON ;CONTEXT SWITCH NOW DONE
JUMPE R,SETRLZ ;DONE IF NULL JOB
HLRZM R,.USHVA ;SET .UPHVA FOR ADDRESS CHECKING AT IRP LEVEL
SKIPN T1,.USREL ;HOLEY PROGRAM?
HLR T1,R
HRRZM T1,.JDAT+JOBREL## ;STORE HIGHEST CORE-UUO ADDRESS IN JOBREL
SKIPL T1,JBTSGN##(J) ;JOB HAVE A REAL HIGH SEGMENT?
SKIPA T1,JBTADR##(T1) ;YES
HRLZS T1 ;SIZE OF SPY SEGMENT OR ZERO IF NOT SPY SEGMENT
LDB T2,[POINT 9,T1,8];CURRENT SIZE -1 OF THE HIGH SEGMENT
SKIPE T1 ;IS THERE A SPY OR HIGH SEGEMNT?
ADDI T2,1 ;YES, ITS ACTUALLY ONE PAGE BIGGER
LDB T1,JBYHSS##
MOVSI T3,REDOMP!SEGMB ;FORCING THE MAP TO BE REDONE?
TDNN T3,JBTSGN##(J)
CAIE T1,(T2) ;HAS THE HIGH SEGMENT SIZE CHANGED SINCE THE
; LAST TIME THIS JOB WAS RUN?
PUSHJ P,MAPHGH## ;YES, REDO THE HIGH SEGMENT PART OF THE MAP
MOVSI T1,REDOMP!SEGMB ;INDICATE MAP HAS BEEN REDONE NOW
ANDCAM T1,JBTSGN##(J)
SETRLZ: MOVE T3,JBTPDB##+0 ;NULL JOB PDB
PUSHJ P,FNDPDS## ;SET UP W
.SKIPE T2,.PDABS##(W) ;DOES THE USER HAVE ADDRESS BREAK SETTINGS?
TLNN T2,(OC.ABE) ;YES, IS HE ENABLED FOR BREAKS
JRST SETRL3
TLZ T2,(OC.BSU) ;CLEAR SET BY UUO
TLZE T2,(1B0) ;CHANGE NEW HARDWARE INTO
TLO T2,(1B9) ; OLD. OR CHANGE OLD
TLZE T2,(1B1) ; SOFTWARE INTO NEW
TLO T2,(1B10) ; ..
TLZE T2,(1B2) ; ..
TLO T2,(1B11) ; ..
TLZE T2,(1B6) ; ..
TLO T2,(1B12) ; ..
CAIA ;
SETRL3: SETZ T2,
.SKIPL .PDABS##(T3) ;CAN USERS USE ADDRESS BREAK?
DATAO APR,T2 ;YES, SETUP BREAK CONDITIONS AND BREAK ADDRESS
MOVEM T2,.CPAPR## ;STORE BREAK CONDITIONS FOR SSEUB
SETRL2: SKIPN R,JBTADR##(J) ;RESTORE R - JOB HAVE CORE IN CORE?
TDZA T1,T1 ;NO, MUST BE THE NULL JOB OR CORE 0
MOVE T1,.JDAT+JOBENB## ;JOB'S APR ENABLE BITS
PJRST SETCNA## ;SETUP APR ENABLE BITS FOR THE USER
; NO ENABLES IF NULL JOB OR NO CORE IN CORE
;ROUTINE TO SETUP USER AND EXEC BASE REGISTERS FOR A JOB
;CALLING SEQUENCE:
; MOVE J,JOB NUMBER
; PUSHJ P,STEUB
;ENTER AT MKADD TO JUST MAKE THE JOB ADDRESSABLE
MKADD:: CAME J,.USJOB ;GO AWAY IF ALREADY ADDRESSABLE
STEUB:: CAILE J,JOBMAX## ;IS THIS A HIGH SEGMENT?
POPJ P, ;YES, THE UBR MUST ALREADY BE SETUP
; OR DOESN'T NEED TO BE (ADDRESSES WILL BE
; MAPPED THROUGH THE EXEC MAP)
PUSH P,T1 ;SAVE A TEMPORARY
HRRZ T1,JBTUPM##(J) ;T1 = THE PAGE NUMBER OF THE USER PAGE MAP PAGE
CONO PI,PI.OFF ;NO INTERRUPTS WHILE CHANGING UBR/SPT
SKIPE T1 ;IF NOT ZERO,
HRRM T1,@.CPSPT## ; SETUP NEW SPT
TDO T1,[LG.LUB+LG.KPM+LG.IAM] ;REQUEST LOADING OF UBR
TRNE T1,17777 ;IS THERE A UPMP
DATAO PAG,T1 ;SET FOR CURRENT USER AND CLEAR THE AM
CONO PI,PI.ON ;BOTH THE SPT AND UBR HAVE BEEN CHANGED
JRST TPOPJ## ;RESTORE T1 AND RETURN
IFN FTXMON,<
;ROUTINES TO SETUP PCS FROM DEVISN.
;CALLING SEQUENCE:
; MOVE F,DDB ADDRESS
; PUSHJ P,SPCS
;ROUTINES CALLING THIS ROUTINE SHOULD CALL SVEU? SO THAT PCS WILL BE
; RESTORED ON A POPJ FROM THE CALLING ROUTINE
SPCS:: PUSH P,T1 ;SAVE A TEMP
HRRZ T1,DEVISN(F) ;GET SECTION NUMBER FOR I/O
MOVSI T1,<(LG.LPC)>(T1) ;LOAD PREVIOUS CONTEXT SECTION
DATAO PAG,T1 ;PREVIOS CONTEXT IS ADDRESSABLE
JRST TPOPJ## ;RESTORE T1 AND RETURN
>
IFE FTXMON,<
SPCSB==:SVEUB
SPCSF==:SVEUF
SPCS==:CPOPJ##
>
IFN FTEMRT,<
;ROUTINES TO HANDLE ACCOUNTING METERS
;RETURN EBOX COUNTS FROM CURRENT UPT IN T1 AND T2
GETEBT::RDEACT T1 ;READ EBOX COUNTS INTO T1,T2
POPJ P, ;RETURN
GETMBT::RDMACT T1 ;SAME FOR MBOX COUNTS
POPJ P,
;ROUTINE TO TURN ACCOUNTING METERS ON AND OFF
; CALLED BY CLOCK1 TO EXCLUDE MONITOR OVERHEAD FROM USER RUNTIME
; ACCMON AND ACCMOF PRESERVE ALL ACS
ACCMON::PUSH P,T1
PUSH P,T2 ;SAVE T1,T2
CONI MTR,T1 ;GET PI ASSIGNMENT, TIME BASE ON/OFF
TRO T1,MO.LAC!MO.AEN!MO.AIP!MO.AO ;MAKE SURE LOAD ACCT, EXEC NO PI
; PI, ACCT METER ON
MOVE T2,CNFST2## ;GET CNFST2
TRNE T2,ST%XPI ;EXCLUDE PI FROM USER RUNTIME?
TRZ T1,MO.AIP ;YES, THEN DON'T INCLUDE
CONO PI,PI.OFF ;TURN OFF PI'S SO ACCOUNTING METER AND PERF METER
; WILL STAY IN SYNC
CONO MTR,(T1) ;SET STUFF, TURN METER ON
SKIPE .CPAPS## ;IF ACCT/PERF METER SYNC,
PUSHJ P,SCDPMR ;GO TURN PERFORMANCE METER ON IF NECESSARY
CONO PI,PI.ON ;BACK ON
POP P,T2 ;RESTORE T2
JRST TPOPJ## ;T1 AND RETURN
;TURN OFF ACCOUNTING METER
ACCMOF::PUSH P,T1 ;SAVE AN AC
CONI MTR,T1 ;GET PI ASSIGNMENT, OTHER STUFF
ANDI T1,7 ;ONLY PI ASSIGNMENT
TRO T1,MO.LAC ;LOAD ACCOUNTING ENABLES - ZILCH
CONO PI,PI.OFF ;TURN OFF PI'S
CONO MTR,(T1) ;STOP THE CLOCK
SKIPE .CPAPS## ;ACCOUNTING/PERF SYNC?
PUSHJ P,STPPMR ;YES, TURN OFF PERFORMANCE METER
CONO PI,PI.ON ;PI BACK ON AGAIN
PJRST TPOPJ## ;RESTORE T1 AND RETURN
;STILL IN FTEMRT CONDITIONAL
;CLEAR EBOX, MBOX COUNT FOR CURRENT UPT
; THESE ROUTINES PRESERVE ALL AC'S
CLREMB::DATAI PAG,1(P) ;WRITE OUT ALL THE BITS
DATAO PAG,1(P)
SETZM .UPMP+.LMEBL ;LOW ORDER BITS FIRST SO NO OVERFLOW
SETZM .UPMP+.LMEBH ;THEN HIGH ORDER
SETZM .UPMP+.LMMBL ;LOW ORDER FIRST
SETZM .UPMP+.LMMBH ;THEN HIGH
POPJ P, ;RETURN
>;END IFN FTEMRT
SUBTTL IOCSS - I/O SERVICE SUBROUTINES (UUOCON AND DEVICE ROUTINES)
;ROUTINE TO SAVE AND OPTIONALLY SET UP THE USER BASE REGISTER
; AND RESTORE IT ON A CPOPJ OR CPOPJ1 RETURN
;CALLING SEQUENCE:
; PUSHJ P,SVEUB ;TO SAVE USER BASE REGISTER
;OR
; PUSHJ P,SVEUB ;TO SAVE USER BASE REGISTER AND SETUP
; ;USER BASE REGISTER FOR JOB IN J
;ALWAYS RETURN HERE
SVEUF:: PUSH P,T1 ;SAVE A TEMPORARY
PUSH P,@.CPSPT##
DATAI PAG,T1 ;GET THE USER BASE REGISTER
PUSH P,J ;SAVE J
LDB J,PJOBN## ;GET THE JOB NUMBER OF JOB CURRENTLY USING
; THIS DEVICE
PUSHJ P,MKADD ;SETUP THE UBR SO CURRENT JOB IS ADDRESSABLE
POP P,J ;RESTORE J
JRST SSEU1 ;SAVE THE PREVIOUS CONTENTS OF THE UBR AND EBR
SVEUB:: PUSH P,T1 ;SAVE A TEMPORARY
PUSH P,@.CPSPT##
DATAI PAG,T1 ;GET THE CONTENTS OF THE USER BASE REGISTER
PUSHJ P,MKADD ;SETUP THE UBR FOR THE JOB WHOSE JOB NUMBER
; IS IN J
JRST SSEU1 ;SAVE THE PREVIOUS CONTENTS OF THE UBR
SSEUB:: PUSH P,T1 ;SAVE A TEMPORARY
PUSH P,@.CPSPT##
DATAI PAG,T1 ;GET THE CONTENTS OF THE USER BASE REGISTER
SSEU1: EXCH T1,-2(P) ;GET THE CALLER'S PC AND SAVE THE CONTENTS
; OF THE UBR
MOVEM T1,1(P) ;SAVE THE CALLER'S PC IN A TEMPORARY LOCATION
; ON THE STACK
MOVE T1,-1(P) ;RESTORE T1 TO ITS CONTENTS ON ENTRY
DATAI APR,-1(P) ;SAVE ORIGINAL BREAK CONDITIONS
; THIS DOES NOT STORE BREAK ADDR
DATAO APR,[0] ;NO ADDRESS BREAKS
PUSHJ P,@1(P) ;RETURN TO THE CALLER LEAVING .+1 ON THE
; STACK SO WHEN THE CALLER DOES A POPJ OR
; A CPOPJ1, CAN RESTORE THE PREVIOUS CONTENTS
; OF THE UBR
CAIA ;CPOPJ RETURN
AOS -3(P) ;CPOPJ1 RETURN - BUMP RETURN PC
CONO PI,PI.OFF ;DON'T ALLOW INTERRUPTS UNTIL UBR/SPT AGREE
POP P,@.CPSPT##
EXCH T1,-1(P) ;GET THE PREVIOUS CONTENTS OF THE UBR
DATAI PAG,1(P) ;READ INTO A TEMP
CAMN T1,1(P) ;GOING TO CHANGE IT TO WHAT IT IS?
JRST SSEU2 ;YES, DON'T CLEAR THE PAGING MEMORY
TDO T1,[LG.KPM+LG.IAM] ;DON'T UPDATE METERS
DATAO PAG,T1 ;RESTORE THE UBR
SSEU2: CONO PI,PI.ON ;SAFE TO ALLOW INTERRUPTS
POP P,T1 ;RESTORE BREAK CONDITIONS
HRR T1,.CPAPR## ;GET BREAK ADDRESS
DATAO APR,T1 ;RE-ENABLE ADDRESS BREAK
JRST TPOPJ## ;RESTORE T1 AND RETURN
;SUBROUTINE TO SAVE CURRENT PCS, SET IT TO (T1) AND RESTORE IT TO PREVIOUS
; VALUE ON CPOPJ OR CPOPJ1 RETURN
SVPCS:: PUSH P,(P) ;COPY AS SECOND WORD OF PC
XSFM -1(P) ;READ FLAGS AND PCS
PUSH P,-1(P) ;COPY OLD FLAGS AND PCS TO TOP OF THE STACK
HRRM T1,-2(P) ;STORE DESIRED (NEW) PCS
PUSH P,T1 ;SAVE ARGUMENT
HRLOI T1,37 ;IN CASE IN SECTION 0,
ANDM T1,-2(P) ; IN PC SO WE DON'T XJRSTF INTO THE BOONIES
POP P,T1 ;RESTORE ARGUMENT
PUSHJ P,[XJRSTF -3(P)];CALL CALLER AS A COROUTINE WITH NEW PCS SETUP
CAIA ;NON-SKIP RETURN
AOS -3(P) ;SKIP RETURN, PROPAGATE IT
PUSH P,-3(P) ;COPY RETURN PC TO THE TOP OF THE STACK
PUSH P,T1 ;SAVE T1 AS RETURNED FROM SUBROUTINE CALL
HRLOI T1,37 ;CLEAR FLAGS
ANDM T1,-1(P) ; IN CASE IN SECTION 0
POP P,T1 ;RESTORE T1
ADJSP P,-5 ;RESET STACK
XJRSTF 4(P) ;RESTORE OLD PCS AND RETURN
;COROUTINE TO SAVE THE CALLER'S PCS, AND RESTORE IT UPON THE CORETURN.
;CALLING SEQUENCE:
; PUSHJ P,SSPCS
; ALWAYS RETURNS HERE
;RESTORES PCS ON RETURN
SSPCS:: EXCH T1,(P) ;SAVE CALLER'S T1, GET RETURN PC
MOVEM T1,1(P) ;PUT IT WHERE COROUTINES DO
XSFM T1 ;GET CURRENT PCS
ANDI T1,MXSECN ;KEEP ONLY SECTION NUMBER
EXCH T1,(P) ;SAVE FOR CORETURN AND RESTORE CALLER'S T1
PUSHJ P,@1(P) ;CALL CALLER
CAIA ;PROPAGATE NON-SKIP
AOS -1(P) ; VS SKIP RETURN
EXCH T1,(P) ;SAVE T1 AND GET ORIGINAL PCS
MOVSI T1,<(LG.LPC)>(T1) ;LOAD PREVIOUS CONTEXT SECTION
DATAO PAG,T1 ;SET UP PCS
JRST TPOPJ## ;RESTORE T1 AND RETURN TO CALLER'S CALLER
;ROUTINE TO SETUP PCS AS DESIRED BY THE CALLER
;CALLING SEQUENCE:
; MOVEI T1, SECTION #
; PUSHJ P,STPCS
; ALWAYS RETURN HERE WITH PCS SETUP
;PRESERVES ALL REGISTERS
STPCS:: PUSH P,T1 ;IN CASE OF BITS
ANDI T1,MXSECN ;MASK DOWN TO JUST SECTION NUMBER
MOVSI T1,<(LG.LPC)>(T1) ;LOAD PREVIOUS CONTEXT SECTION
DATAO PAG,T1 ;SETUP PCS AS DESIRED
JRST TPOPJ## ;RESTORE T1 AND RETURN
;ROUTINE TO CONVERT AN IOWD TO ABSOLUTE IOWDS
;FOLLOWING THE PAGING OF A JOB
;CALLING SEQUENCE:
; MOVE T2,IOWD
; MOVEI P1,0 ;FIRST CALL
; MOVE P3,LOC OF CHANNEL DATA BLOCK
; MOVE P4,FRAME-COUNT,,CHARS/WD
; PUSHJ P,MAPIOW
; RETURN HERE IF NOT ENOUGH MONITOR FREE CORE
; RETURN HERE - P2=ADDRESS OF FIRST IOWD
; P1=WHERE NEXT IOWD WILL BE STORED
; P2=LOC OF IOWD WE JUST STORED, IF A DX10
MAPIO:: TLNN T2,-1 ;0 OR CHANNEL JUMPS ARE ILLEGAL
STOPCD CPOPJ##,DEBUG,IEZ, ;++IOWD EQUALS ZERO
PUSH P,U ;SAVE U
HLLZ U,CHB22B##(P3) ;GET CHANNEL-TYPE WORD
TLNE U,CP.RH2##!CP.KLP##!CP.KNI## ;INTERNAL CHANNEL DEVICE?
TROA U,4 ;YES
LDB U,[POINT 2,U,1] ;NO, GET CHAN TYPE ELSEWHERE
HLL U,P4 ;PRESERVE FRAMECOUNT
PUSH P,T1 ;SAVE ALL ACS THAT ARE USED SINCE THEY
PUSH P,P4 ; ARE PROBABLY IMPORTANT TO THE CALLERS
PUSH P,P3 ; OF MAPIOW
PUSH P,T2 ; ..
PUSH P,T3 ; ..
PUSH P,T4 ; ..
JUMPN P1,MAPIO1 ;P1 IS NON-ZERO IF NOT THE FIRST CALL
PUSHJ P,GCH4WD ; ..
JRST MAPIO8 ;NONE AVAILABLE
MOVE P1,T1 ;ADDRESS OF THE FOUR WORD BLOCK
MOVE P2,T1 ;ADDRESS OF THE IOWD LIST
HRLI P1,-3 ;THE NUMBER OF WORDS LEFT IN THIS BLOCK
SETZM 3(P1) ;ZERO THE LAST WORD OF THE BLOCK
TRNE U,4 ;INTERNAL CHANNEL DEVICE?
SETZM CHNTCW##(P3) ;ACCUMULATE WORD-COUNT IN CHNTCW (FOR RH20)
MAPIO1: PUSHJ P,CHKMOR ;GET ANOTHER FOUR WORD BLOCK AND LINK IT
; TO THE CURRENT BLOCK IF ABOUT TO USE
; THE LAST WORD OF THE CURRENT BLOCK
JRST MAPIO7 ;NO MORE FOUR WORD BLOCKS
MOVE P4,-2(P) ;RESTORE THE IOWD TO P4
MOVE T2,P4 ;T2 AND P4 = IOWD
HLROS P4 ;P4 = -WORD COUNT
ADDI T2,1 ;POINT AT REAL ADR
LDB P3,DEYISN## ;GET RUNNING SECTION FOR I/O
ADDM P3,DEVISN(F) ;UPDATE DEVISN FOR THIS I/O OPERATION
SETZ P3, ;NO RUNNING TOTAL NOW
DPB P3,DEYISN## ;ZAP REMEMBERANCE OF CROSSING SECTION BOUNDARIES
HRRZ P3,T2 ;VIRTUAL ADDRESS WITHIN SECTION
MAPIO2: PUSHJ P,[PUSH P,P3 ;T3 = CURRENT ABSOLUTE ADDRESS
PUSHJ P,V2PADR;GET IT
JRST P3POPJ## ;ILLEGAL PAGE(S)
AOS -1(P) ;PROPAGATE SKIP
JRST P3POPJ##] ;GOOD RETURN
SKIPGE USRHCU## ;IF A SAVE IS IN PROGRESS,
SKIPA ; THEN, THIS IS OK
JRST S..AAO ;ACCESS ALLOWED OFF
; IOWD HAS BEEN ADDRESS CHECKED)
MOVEI T1,0 ;T1 = AMOUNT ACCUMULATED SO FAR
MOVE T2,T3 ;T2 = ABSOLUTE ADDRESS (IOWD STYLE)
SUBI T2,1 ;MAKE AN IOWD
PUSH P,T2 ;SAVE THE ADDRESS
ANDI T2,PG.BDY## ;EXTRACT THE WORD NUMBER
SUBI T2,PAGSIZ##-1 ;CALCULATE THE NUMBER OF WORDS TO DO INTO THIS PAGE
SKIPN T2 ;IF ITS ZERO DO A WHOLE PAGE WORTH
MAPIO3: MOVNI T2,PAGSIZ## ; ..
SUB P4,T2 ;ADD -NUMBER OF WORDS ON THIS PAGE TO
; IOWD WORD COUNT
ADD T1,T2 ;ACCUMULATE IN TOTAL WORD COUNT
JUMPGE P4,MAPIO5 ;JUMP IF THE ORIGIONAL WORD COUNT IS EXHAUSTED
SUB P3,T2 ;UPDATE VIRTUAL ADDRESS BY AMOUNT DONE
MOVN T4,T2 ;SET T4 SO TEST WILL FAIL IF 22-BIT CHAN AND
SKIPE U ; NO ROOM FOR ANOTHER PAGE IN IOWD
CAML T1,[EXP -37777+PAGSIZ##] ;OTHERWISE SET T3=CURRENT PAGE
ADD T4,T3 ;T4 = CURRENT PHYSICAL ADDRESS WITHIN SEGMENT
PUSHJ P,[PUSH P,P3 ;T3 = NEXT PHYSICAL ADDRESS WITHIN PAGE
PUSHJ P,V2PADR;GET IT
JRST P3POPJ## ;ILLEGAL PAGE(S)
AOS -1(P) ;PROPAGATE SKIP
JRST P3POPJ##] ;GOOD RETURN
STOPCD .,JOB,AAO, ;++ACCESS ALLOWED IS OFF
MOVNI T2,PAGSIZ## ;ASSUME WILL DO ANOTHER WHOLE PAGE
CAMLE P4,[-PAGSIZ##] ;LESS THAN A PAGE LEFT IN USER IOWD
MOVE T2,P4 ;YES, WILL JUST DO THAT MUCH
ADD T2,T1 ;GET UPDATED WORD COUNT
TRNN U,4 ;INTERNAL CHANNEL DEVICE?
JRST MAPI3A ;NO
CAME T2,[-600000] ;DON'T GENERATE IOWD WHOSE LH
CAMN T2,[-030000] ; LOOKS LIKE AN RH20 CHANNEL JUMP
JRST MAPIO4
MAPI3A: CAMN T4,T3 ;ARE THE TWO PAGES ADJACENT IN PHYSICAL MEMORY?
JRST MAPIO3 ;YES, CONTINUE ON CURRENT IOWD
MAPIO4: POP P,(P1) ;STORE THE IOWD ABSOLUTE ADDRESS
PUSHJ P,DXFIX ;ADJUST IOWD IF A DX10
JRST MAPI6A ;NO SPACE
JUMPL U,MAPIO6 ;DONE IF FRAMECOUNT EXHAUSTED
AOBJN P1,MAPIO2 ;CONTINUE IF THERE IS ROOM IN THE FOUR WORD BLOCK
PUSHJ P,GETMOR ;GET ANOTHER FOUR WORD BLOCK
JRST MAPI6A ;WHOOPS! NONE AVAILABLE
JRST MAPIO2 ;MAP THE REST OF THE IOWD
MAPIO5: POP P,(P1) ;STORE THE IOWD ABSOLUTE ADDRESS
ADDB P4,T1 ;ADD THE RESIDUAL WORD COUNT TO THE ACCUMULATED
; WORD COUNT
PUSHJ P,DXFIX ;PERFORM FIXUPS FOR DX10
JRST MAPI6A ;OUT OF SPACE
; THE ALREADY ABSOLUTE IOWD AND RETURN
MAPIO6: AOBJN P1,.+1 ;BUMP THE POINTER TO THE NEXT FREE WORD
SETZM (P1) ;ZERO IT SO THE LIST IS TERMINATED
AOS -7(P) ;SET FOR SKIP (WIN) RETURN
MAPI6A: HLRZS P3 ;CURRENT SECTION OFFSET FROM DEVISN
HLRE T1,-2(P) ;GET WORD COUNT
MOVNI T1,-1(T1) ;POSITIVE WORD COUNT + 1
ADD T1,-2(P) ;+ STARTING ADDRESS - 1
TRNN T1,-1 ;I/O END AT A SECTION BOUNDARY?
ADDI P3,1 ;YES, THEN START NEXT OP IN NEXT SECTION
DPB P3,DEYISN## ;SAVE THAT FOR NEXT TIME
MAPIO7: SKIPGE -3(P) ;IF WE WANT IT STORED,
TRNE U,5 ;TYPE 0 OR 2 OR 4 CONTROLLER?
JRST MAPIO8 ;NO, DON'T DO NEXT
HRRZS U ;CLEAR POSSIBLE FRAMECOUNT
LSH U,-1
MOVE T3,P1 ;GET ADDR OF LAST IOWD FOR BYTE PTR'S
LDB T1,ADRPT2##(U) ;GET ADDR FIELD FROM LAST IOWD
HLRO P4,-1(T3) ;WORD COUNT
ASH P4,@ASH22B##(U) ;4 BITS DON'T COUNT IF 22-BIT
SUB T1,P4 ;DETERMINE ENDING DATA ADDRESS
DPB P1,ADRPT4##(U) ;PUT ADDR OF END OF IOWD LIST
MOVE T4,-3(P)
MOVEM T1,CHNTCW##(T4)
MAPIO8: POP P,T4 ;RESTORE ACS
POP P,T3 ; ..
POP P,T2 ; ..
POP P,P3 ; ..
POP P,P4 ; ..
POP P,T1 ; ..
PJRST UPOPJ## ;GIVE WIN OR LOSE RETURN
;ROUTINE TO FINISH UP AN RH20 IO LIST
;PRESEVES T1
RH2ND:: PUSH P,T1
PUSH P,U
MOVEI U,4 ;TELL THE WORLD IT AN RH20
MOVEI T3,177
ANDB T3,CHNTCW##(P3) ;NO SWEAT IF AN EVEN MULTIPLE OF 200 WORDS
JUMPE T3,RH2ND1
TLNE S,IOSUPR##
TRNN S,UDSX## ;ASSUME USER KNOWS IF HE'S FORMATTING
PUSHJ P,CHKMOR ;NOT EVEN MULTIPLE, HAVE TO INSERT A THROW-AWAY WORD
JRST RH2ND1 ;NO MORE ROOM, LET IT GO ANYWAY
MOVN T3,CHNTCW##(P3) ;COMMPUTE NO OF WORDS TO 0-FILL
ADDI T3,200+RH2TLS## ;NO OF WORDS AND LAST+TRA
LSH T3,^D22 ;POSITION IT
MOVEM T3,(P1) ;STORE THE THROW-AWAY IOWD
TLZ T3,077777 ;JUST LAST+TRA
AOBJN P1,RH2ND2 ;STORE TCW AND EXIT (AOBJN ALWAYS JUMPS)
RH2ND1: MOVSI T3,RH2LST## ;LIGHT LAST-BIT IN IOWD
IORB T3,-1(P1)
LDB T2,[POINT 11,T3,13] ;GET WORDCOUNT
TDNE T3,[17,,-1] ;ADR = 0 IS SPECIAL
ADD T3,T2 ;ADDR + N
TLZ T3,077760 ;WDCNT SHOULD GO TO 0
RH2ND2: MOVEM T3,CHNTCW##(P3) ;SAVE EXPECTED TERM WORD
POP P,U
PJRST TPOPJ## ;AND RETURN TO CALLER
;SUBROUTINE TO CHECK TO SEE IF THE CURRENT FOUR WORD BLOCK IS EXHAUSTED
; AND IF SO GET ANOTHER ONE IF ANY ARE AVAILABLE. IF THE NEXT FOUR WORD
; BLOCK IT OBTAINS IS ADJACENT TO THE CURRENT ONE, IT SIMPLY RETURNS. IF
; IT IS NOT, A LINK WORD LINKING THE CURRENT FOUR WORD BLOCK TO THE
; NEW FOUR WORD BLOCK IS SETUP IN THE FOURTH WORD OF THE CURRENT BLOCK
;CALLING SEQUENCE:
; MOVE P1,AOBJN POINTER TO CURRENT BLOCK
; MOVEI U,4 IF RH20
; 3 IF DX10
; 0 IF NOT RH20 OR DX10
; PUSHJ P,CHKMOR
; ... RETURN HERE IF NO MORE FOUR WORD BLOCKS
; ... RETURN HERE IF CURRENT FOUR WORD BLOCK NOT FILLED OR
; NEXT FOUR WORD BLOCK OBTAINED
;P1 = AOBJN POINTER TO CURRENT OR NEW BLOCK
CHKMOR::JUMPL P1,CPOPJ1## ;CONTINUE IF ANY WORDS LEFT IN THIS BLOCK
GETMOR::PUSHJ P,GCH4WD ;GET 1 CORE BLOCK
POPJ P, ;NO MORE AVAILABLE
CAIE T1,1(P1) ;IS THIS BLOCK ADJACENT TO THE LAST BLOCK?
JRST GETMR1 ;NO, ADD A LINK
HRLI P1,-4 ;YES, FOUR WORDS LEFT TO GO (LAST WORD IN
; THE LAST BLOCK AND THREE WORDS IN NEW BLOCK)
JRST CPOPJ1## ;RESTORE T2 AND GIVE OK RETURN
GETMR1:
TRNE U,4 ;RH20?
HRLI T1,RH2JMP## ;YES, MAKE RIGHT STYLE JUMP-WORD
TRC U,3
TRCN U,3 ;CHECK CHL TYPE
HRLI T1,CCHJGO## ;DX10 STYLE CHL JUMP
MOVEM T1,0(P1) ;LINK TO THE NEW BLOCK
MOVE P1,T1 ;P1 = POINTER TO NEW BLOCK
HRLI P1,-3 ;NUMBER OF WORDS LEFT TO GO IN THE CURRENT BLOCK
JRST CPOPJ1## ;AND SKIP RETURN
;ROUTINE TO CONVERT A VIRTUAL ADDRESS (USER OR EXEC) TO A PHYSICAL
; ADDRESS
;CALLING SEQUENCE:
; MOVE F,ADDRESS OF DDB WITH DEVISC (SECTION NUMBER FOR I/O)
; SETUP IN IT
; MOVE P3,VIRTUAL ADDRESS
; PUSHJ P,V2PADR ;GET PHYSICAL ADDRESS WHICH CORRESPONDS TO VIRTUAL ADDRESS
; RETURNS HERE IF PAGE NOT ACCESSIBLE
; RETURNS HERE, T3 = PHYSICAL ADDRESS CORRESPONDING TO C(DEVISN)B18+(P3)
;
V2PADR: SKIPL DEVISN(F) ;IOWD ALLOWED TO CROSS A SECTION BOUNDARY?
TLNN P3,-1 ;NO, DOES IT?
SKIPA T3,T1 ;IOWD IS OK, SAVE T1
POPJ P, ;IOWD CROSSES SECTION BOUNDARY WHEN IT SHOULDN'T
HRLZ T1,DEVISN(F) ;SECTION NUMBER WHERE ORIGINAL IOWD STARTED
ADD P3,T1 ;SECTION NUMBER FOR I/O
HLRZ T1,P3 ;PCS SECTION
PUSHJ P,SVPCS ;SAVE PCS AND SET IT TO SECTION NUMBER FOR I/O
MOVE T1,T3 ;RESTORE T1
MOVE T3,DEVMOD(F)
IFE FTSPL,<
TLNN T3,DVDSK ;IF A DSK
>
IFN FTSPL,<
SKIPL DEVSPL(F) ;SPOOLED DDBS ARE ALWAYS A DSK
TLNE T3,DVDSK ;IF A DSK
CAIA
>
SKIPN T3
SKIPL S
SKIPA T3,[XCT 4,[MAP T3,(P3)]]
MOVSI T3,(MAP T3,(P3))
SE1ENT ;SAVE CALLER'S SECTION, ENTER SECTION 1
XCT T3 ;MAP OR PXCT OF A MAP
TLNN T3,(1B1) ;BAD FAIL OR
TLNN T3,(17B5)
POPJ P, ;YES TO EITHER, WILL FAULT
V2PAD1: TLZ T3,777760 ;CLEAR ACCESS BITS
JRST CPOPJ1## ;REF OK. WIN.
;ROUTINE USED TO HANDLE 22-BIT CHNLS AND PERFORM IOWD TRANSFORMATIONS
;FOR THE DX10 TAPE CHL. CALLING SEQUENCE:
; MOVE T1,-WDS TO XFER
; MOVE P1,ADDRS OF CURRENT IOWD
; CHARS/WD WAS FOUND IN THE ORIGINAL CALL TO MAPIO
; PUSHJ P,DXFIX
; ... ;RETURN HERE IF NO MORE FREE SPACE
; ... ;RETURN HERE IF OK
DXFIX: TRNE U,4 ;RH20?
JRST RH2FIX ;YES, DO DIFFERENTLY
HRRZ T4,U
CAIE T4,3 ;CHECK CHL TYPE
JRST [DPB T1,WDCPNT##(U)
JRST CPOPJ1##] ;HANDLE NON-DX10 CHLS
MOVE T4,-5(P) ;RESTORE CHAR/WD
IMULI T1,0(T4) ;CONVERT TO BYTE COUNT
AOS 0(P1) ;DX10 LIKES ADDRS RATHER THAN ADDRS-1
HLRZ T3,U ;FRAME COUNT USER SET
JUMPE T3,DXFIX0 ;NONE
MOVNS T3
CAML T3,T1 ;MORE THAN HE WANTS?
MOVE T1,T3 ;YES, GET WHAT WAS REQUESTED
HRLZ T3,T1 ;FRAMECOUNT
ADDB T3,U ;UPDATE MAX LEFT
TLNN T3,-1 ;ROOM FOR MORE?
HRROS U ;NO, INDICATE WE'RE DONE
DXFIX0: CAML T1,[-17777] ;ROOM FOR THIS
JRST DXFIX2 ;YES - JUST STORE AND EXIT
MOVE T3,MCHTAB(T4) ;MAX CHARS / XFER CMD
SUB T1,T3 ;SUBTRACT MAX FOR THIS ONE
DPB T3,WDCPNT##(U) ;STORE IN IOWD
PUSH P,0(P1) ;SAVE PNTR
AOBJN P1,DXFIX1 ;SEE IF ROOM FOR MORE
PUSH P,T1 ;NO -SAVE COUNT
PUSHJ P,GETMOR ;GET MORE SPACE
JRST DXFIX3 ;RAN OUT OF SPACE
POP P,T1 ;RESTORE COUNT
DXFIX1: POP P,T3 ;GET LAST POINTER
MOVE T4,-5(P) ;RESTORE T4 (CHARS/WD)
ADD T3,MWDTAB(T4) ;ADD MAX WORDS OFFSER
MOVEM T3,0(P1) ;NEW PARTIAL PNTR
JRST DXFIX0 ;5ROCEED
DXFIX2: DPB T1,WDCPNT##(U) ;STORE RESIDUE
HRL P2,P1 ;LOC OF THE IOWD
JRST CPOPJ1## ;SUCCESS RETURN
DXFIX3: POP P,T1 ;PRUNE PDL
JRST TPOPJ## ;PRUNE & EXIT (FAIL)
;THE BYTE PACKING MODES OF THE DX10 WILL ALLOW 4,5 & 6 BYTES / WORD
;THESE TABLES ARE USED TO TRANSLATE THIS INFO INTO 1) THE MAX CHARS
;THAT WILL EXACTLY FILL THE 2) MAX NO. OF WDS PER IOWD
;ALLOWING 2^13-1 BYTES / IOWD.
MCHTAB=.-4
-<17777/4>*4 ;4 BYTE/WD = 8188 BYTES
-<17777/5>*5 ;5 BYTE/WD = 8190 BYTES
-<17777/6>*6 ;6 BYTE/WD = 8190 BYTES
MWDTAB=.-4
17777/4 ;4 BYTE/WD = 2047 WDS
17777/5 ;5 BYTE/WD = 1638 WDS
17777/6 ;6 BYTE/WD = 1365 WDS
;ROUTINE TO HANDLE RH20 DEVICES
RH2FIX: SKIPE (P1) ;UNLESS THROW-AWAY IOWD
AOS (P1) ;RH20 LIKES ADDRESS
MOVNS T1 ; AND POSITIVE WRDCNT
HLRZ T3,U ;GET FRAME COUNT
JUMPE T3,RH2FX0 ;DO WE HAVE FC?
MOVE T4,-5(P) ;YES, RESTORE CHAR/WD
IDIVI T3,(T4) ;FC TO WC
SKIPE T4 ;EXTRA FRAMES?
ADDI T3,1 ;YES, ADD A WORD
CAMLE T1,T3 ;TAKE SMALLER
MOVE T1,T3
RH2FX0: MOVE T3,-4(P)
ADDM T1,CHNTCW##(T3) ;ACCUMULATE WDCNT
RH2FX1: CAIG T1,3600 ;IF LESS THAN 12 BITS,
JRST RH2FX3 ; DONT HAVE TO FIDDLE WITH IT
MOVEI T3,3600+RH2TRX## ;ONLY CAN DO 11 BITS IN ONE IOWD
DPB T3,WDCPNT##+3 ;SAVE THIS IOWD
SUBI T1,3600 ;ACCUMULATE WHAT WE'VE DONE SO FAR
PUSH P,(P1) ;SAVE PARTIAL IOWD
AOBJN P1,RH2FX2 ;GO IF ROOM FOR ANOTHER IOWD
PUSH P,T1 ;SAVE WDCNT
PUSHJ P,GETMOR ;GET ANOTHER 4-WORD BLOCK
JRST DXFIX3 ;NO MORE - GIVE LOSE RETURN
MOVEI T2,0 ;RESET T2 TO BEGINNING OF PAGE
POP P,T1 ;RESTORE COUNT
RH2FX2: POP P,T3 ;RESTORE PARTIAL IOWD
TDNE T3,[17,,-1] ;IF NOT A SKIP-IOWD
ADDI T3,3600 ;UPDATE ADDR
MOVEM T3,(P1) ;SAVE NEW IOWD (ONLY ADR USED)
JRST RH2FX1 ;AND SET WDCNT FOR NEXT PIECE
RH2FX3: TRO T1,RH2TRX## ;INDICATE THIS IS A DATA-IOWD
DPB T1,WDCPNT##+3 ;STORE WDCNT AND TRA-BIT
JRST CPOPJ1## ;INDICATE WE WON
;SUBROUTINE TO REVERSE THE IOWDS FOR A READ-OPPOSITE
;WORKS ONLY FOR AN RH20 DEVICE
;CALL WITH T1=IORB T2=WORDCOUNT
;RETURNS WITH T1=IORB, THE LIST REVERSED
;RETURNS T2=ORIGINAL LH OF IOWD WHICH GOT CHANGED,,ITS ADDRESS
REVCCW::HRRZ T3,TRBXCW(T1)
;FALL INTO REVCC
;SUBROUTINE TO REVERSE IOWDS
;CALL WITH T2=WRDCNT, T3=ADDR OF IO LIST
;RETURNS WITH IO LIST REVERSED
;PRESERVES T1
REVCCD:: ;(DOESNT GUARANTEE T1)
REVCC: JUMPE T2,CPOPJ## ;WORDCOUNT OF 0 WILL CAUSE A CRASH
PUSHJ P,SAVE4##
SETZ P1,
PUSH P,T3
REVCC1: SKIPN P2,(T3)
SOJA T3,REVCC5
TLNE P2,JMPRH2##
AOJA P1,REVCC2
HRRZ T3,P2
JRST REVCC1
REVCC2: LDB T4,CNTPP2##
CAMLE T4,T2
JRST REVCC3
SUB T2,T4
JUMPE T2,REVCC4
TLNE P2,RH2LST##
JRST REVCC5
AOJA T3,REVCC1
REVCC3: DPB T2,CNTPP2##
REVCC4: TLO P2,RH2LST##
REVCC5: MOVE P4,T3
HLL P4,(P4)
MOVEM P2,(T3)
POP P,T2
;HERE WITH P1= # OF IOWDS, T2 POINTS AT 1ST IOWD, T3 POINTS AT LAST IOWD
REVCC6: SOJLE P1,REVCC9
MOVE P3,(T3)
MOVE P2,(T2)
TLZE P3,RH2LST##
TLO P2,RH2LST##
PUSHJ P,REVIOW
MOVEM P2,(T3)
MOVE P2,P3
PUSHJ P,REVIOW
MOVEM P2,(T2)
SOJLE P1,REVCCA
ADDI T2,1
MOVE T4,(T2)
TLNN T4,JMPRH2##
HRR T2,T4
MOVEI P3,-1(P1)
HRRZ T3,T2
REVCC7: AOSA T3
REVCC8: HRR T3,T4
MOVE T4,(T3)
TLNN T4,JMPRH2##
JRST REVCC8
SOJG P3,REVCC7
JRST REVCC6
REVCC9: JUMPL P1,REVCCA
MOVE P2,(T2)
PUSHJ P,REVIOW
MOVEM P2,(T2)
REVCCA: MOVE T2,P4
POPJ P,
REVIOW: LDB T4,CNTPP2##
TLCE P2,RH2REV##
JRST [SUBI P2,-1(T4)
POPJ P,]
ADDI P2,-1(T4)
POPJ P,
;ROUTINE TO RETURN FREE CORE USED FOR MAPPING IOWDS.
;CALLING SEQUENCE:
; MOVE T1,ADDRESS OF IOWD LIST
; PUSHJ P,RTNIOW
; ALWAYS RETURN HERE
RTNIOW::PUSHJ P,SAVE1## ;SAVE P1
HRRZ P1,T1 ;P1 = ADDRESS OF THE IOWD LIST
RTNIO1: MOVEI T1,1 ;GIVE BACK ONE FOUR WORD BLOCK
HRRZ T2,P1 ;ADDRESS OF THE BLOCK
MOVE T3,3(P1) ;LAST WORD OF BLOCK
TLNN T3,577777 ;AN IOWD?
SKIPA P1,T3 ;NO, THEN THIS IS THE LAST BLOCK
; OR A LINK TO THE NEXT BLOCK
ADDI P1,4 ;ADDRESS OF THE NEXT BLOCK
; (ITS ADJACENT TO THE CURRENT BLOCK)
PUSHJ P,RCH4WD ;RETURN BLOCK TO MONITOR FREE CORE
JUMPE P1,CPOPJ## ;JUMP IF THIS IS THE LAST BLOCK
JRST RTNIO1 ;GIVE UP ALL THE BLOCKS
;ROUTINE TO OBTAIN A LOWER-CORE 4-WORD BLOCK
GCH4WD::MOVE T1,NOIOWD## ;IF WE ARE LOW ON IOWD SPACE
CAMGE T1,NUMKON## ; ONLY GIVE AN IOWD
JUMPN P1,CPOPJ## ; FOR THE INITIAL IOWDS
MOVEI T1,1 ;JUST WANT 1 BLOCK
MOVEI T2,LOWPTR## ;POINT TO LOWER-CORE FREE-CORE TABLE
PUSHJ P,GETBIT## ;GET, SET THE BIT
POPJ P, ;NONE AVAILABLE, LOSE
SOS NOIOWD## ;1 LESS IOWD BLOCK
LSH T1,2 ;CONVERT TO 4-WORD STYLE
ADD T1,LOWLOC## ;CONVERT TO ACTUAL ADDRESS
SETZM 3(T1) ;ZERO THE LAST WORD OF THE CURRENT BLOCK
PJRST CPOPJ1## ;AND TAKE GOOD RETURN
;ROUTINE TO RETURN LOWER-CORE 4-WORD BLOCKS
RCH4WD::SUB T2,LOWLOC## ;CONVERT TO RELATIVE ADDRESS
LSH T2,-2 ;/4 TO CONVERT TO BITS
IDIVI T2,^D36 ;COMPUTE WORD ADR, POSITION IN WORD
HRLS T2
ADD T2,LOWPTR## ;SET AOBJN POINTER FOR SETZRS
ADDM T1,NOIOWD## ;1 MORE IOWD BLOCK
PJRST SETZRS## ;CLEAR THE BITS AND RETURN
;ROUTINE TO INVALIDATE ENTIRE CACHE AND VALIDATE CORE
; ALWAYS RETURN CPOPJ, RESPECTS ALL ACS
; LOOP IN ACS WHILE WAITING FOR FLUSH COMPLETION TO MINIMIZE
; MEMORY INTERFERENCE.
CSDMP:: SWPUA ;SWEEP - UPDATE ALL PAGES, INVALIDATE CACHE
PUSHJ P,SAVE3## ;SAVE E3 ACCUMULATORS
DMOVE P1,CSHWAT ;CACHE WAITING INSTRUCTIONS
MOVE P3,CPOPJ##
PJRST P1 ;WAIT IN ACS
CSHWAT: CONSZ APR,LP.CSB ;WAIT FOR CACHE SWEEP TO HAPPEN
JRST P1
IFN FTMP,<
;SUBROUTINE TO CHASE A LINE OUT OF THE CACHE
;ENTER T1=ADDRESS
;EXIT WITH THAT LOCATION NOT IN THE CACHE
;PRESERVES T2-T4
OUCHE:: ANDI T1,777 ;GET LINE NUMBER
SKIP @OUCHTB##
SKIP @OUCHTB##+1
SKIP @OUCHTB##+2
SKIP @OUCHTB##+3
SKIP @OUCHTB##+4
SKIP @OUCHTB##+5
SKIP @OUCHTB##+6
SKIP @OUCHTB##+7
POPJ P,
>
SUBTTL ERRCON - ERROR HANDLING MODULE
;SUBROUTINE TO SWEEP MEMORY TO FIND ADDRESS AND CONTENTS OF BAD WORDS
;IT CALLS CPU INDEPENDENT SUB.(PARERR) TO RECORD DATA ON EACH BAD WORD
;CALL: PUSHJ P,@.CPMPS##
; ALWAYS RETURN WHEN SWEEP OVER (EVEN IF SERIOUS ERROR)
;SWEEP CORE IN ASCENDING ADDRESSES EVEN THOUGH SLOWER, SO DATA STORED ASCENDING
; FOR ERROR REPORTING WITH DAEMON
CPLMPS::PUSHJ P,MAPLOC## ;GET EXEC MAP SLOT
MOVE W,T1 ;SAVE BYTE POINTER TO EXEC MAP SLOT
MOVSI P3,(<PM.DCD>B2+PM.WRT+PM.PUB)
LDB T4,[POINT 14,NWCORE##,26] ;T4=NUMBER OF PAGES TO SCAN
SKIPA P4,[POINT 1,NXMTAB##] ;BYTE POINTER TO NXM TABLE
MPSLP1: AOS P3 ;STEP TO NEXT PAGE
SOJL T4,MPSLP5 ;RESTORE T1 AND RETURN IF SCANNED ALL OF MEMORY
ILDB T1,P4 ;DOES THIS PAGE EXIST?
JUMPN T1,MPSLP1 ;IF NOT, GO BACK FOR NEXT
DPB P3,W ;MAP THE CURRENT PAGE
MOVE P1,T3 ;EVA FOR BEGINNING OF PAGE
CLRPT (P1) ;CLEAR HDW PAGE TABLE FOR NEW MAPPING
MOVEI T2,PAGSIZ## ;NO. OF WORDS/PAGE TO SCAN
PUSHJ P,CSDMP ;SWEEP CACHE
MOVEI T1,@.CPEBR## ;GET EBR
TRZ T1,LG.CSL+LG.CSW;TURN OFF LOOK AND LOAD
CONO PAG,(T1) ;DISABLE THE CACHE
SETOM .CPPSP## ;SET SWEEPING FLAG
CPLMPI::MOVE P2,(P1) ;TEST NEXT LOCATION
MPSLP2: SOJLE T2,MPSLP1 ;IF CURRENT PAGE DONE, MAP NEXT
AOJA P1,CPLMPI ;GO TEST NEXT WORD IN PAGE
;HERE ON BAD WORD FOUND (NXM OR PARITY) - TRAP HAPPENED AND ADDED 3 TO PC
MAP T1,(P1) ;GET THE PHYSICAL ADDRESS OF BAD WORD
PUSH P,P1 ;SAVE THE EVA
PUSH P,T2 ;SAVE THE WORD NUMBER IN CURRENT PAGE
PUSH P,T3 ;SAVE THE POSITION IN THE MAP
PUSH P,T4 ;SAVE # OF PAGES TO SCAN
LDB P1,[POINT 22,T1,35] ;GET JUST THE PHYSICAL ADDRESS OF BAD WORD
PUSHJ P,CPIASN## ;CONVERT TO SEG NUMBER IN J
TDZA T1,T1 ;INDICATE NO ERROR IN MONITOR OR A JOB
SETO T1, ;INDICATE AN ERROR IN MONITOR OR A JOB
MOVE P2,.CPTBD## ;GET BAD DATA WORD STORED BY THE TRAP ROUTINE
PUSHJ P,PARRBD## ;RECORD BAD DATA
POP P,T4 ;RESTORE T4
POP P,T3 ; AND T3
POP P,T2 ; AND T2
POP P,P1 ; AND P1
SETZM .CPPTH## ;CLEAR FLAG THAT TRAP HAPPENED
JRST MPSLP2 ;GO CONTINUE THE SWEEP
MPSLP5: SETZM .CPPSP## ;CLEAR SWEEPING FLAG
CONO PAG,@.CPEBR## ;TURN CACHE BACK ON
PUSHJ P,UNMAP## ;RESTORE EXEC MAP SLOT
POPJ P, ;AND RETURN
SUBTTL BACKGROUND KL10 PERFORMANCE ANALYSIS
IFN FTRSP,<
;BPAUPD -- UPDATE BACKGROUND PERFORMANCE ANALYSIS COUNTS
;CALLED BY CLOCK1 AT CLOCK INTERUPT LEVEL
;
;PRESERVES ALL ACS.
BPAUPD::SKIPE .CPPJB## ;PERFORMANCE METER IN USE BY PERF.?
POPJ P, ;YES, WE CAN'T USE IT THEN
PUSHJ P,SAVT## ;SAVE THE T AC'S
SKIPN T1,.CPBPI## ;PICK UP WHERE WE LAST LEFT OFF
JRST BPAUP5 ;NEVER BEEN HERE, INITIALIZE FIRST
HRRZ T2,T1 ;GET PACTAB INDEX
LSH T2,2 ;AND MAKE INTO 4-WORD .CPBPV INDEX
;NOW SEE HOW MUCH TIME HAS ELAPSED SINCE WE STARTED THIS ITEM COUNTING
CONO PI,PI.OFF ;VALID TIMINGS
RDTIME T3 ;GET TOTAL ELAPSED TIME
DSUB T3,.CPBPT## ;T3:=INCREMENTAL SINCE STARTED
DADD T3,.CPBPV##(T2) ;T3:=TOTAL ITEM ELAPSED TIME
DMOVEM T3,.CPBPV##(T2) ;STORE FOR INTERESTED PARTIES
;NOW READ THE PERFORMANCE METER COUNT AND SAVE IT AWAY
RDPERF T3 ;T3:=INCREMENTAL PERFORMANCE COUNTER
CONO PI,PI.ON ;LET SYSTEM GO AGAIN
DADD T3,.CPBPV##+2(T2) ;T3:=TOTAL PERFORMANCE COUNT FOR THIS ITEM
DMOVEM T3,.CPBPV##+2(T2) ;SAVE IT FOR INTERESTED READERS
;NOW SELECT NEXT CONDITION TO WATCH
AOBJN T1,.+2 ;NEXT ITEM IN BPATAB
BPAUP5: MOVSI T1,-BPATLN## ;INITIALIZE AT START OF BPATAB
WRPAE [PE.CLR] ;ZAP THE COUNTER
MOVE T4,.CPEPT## ;GET ADDRESS OF EPT FOR THIS CPU
SETZM .E0HPA##-.E0MP##(T4) ;CLEAR HIGH ORDER PERF ANAL COUNT
SETZM .E0LPA##-.E0MP##(T4) ;CLEAR LOW ORDER PERF ANAL COUNT
CONO PI,PI.OFF ;AGAIN, NO INTERRUPTS
RDTIME .CPBPT## ;REMEMBER WHEN THIS CONDITION SELECTED
WRPAE BPATAB##(T1) ;TURN ON PERFORMANCE METER
CONO PI,PI.ON ;AND ONCE AGAIN LET SYSTEM GO
MOVEM T1,.CPBPI## ;REMEMBER WHERE IN BPATAB WE ARE
MOVN T4,.CPBPC## ;TICK COUNT BETWEEN SAMPLES
MOVEM T4,.CPBPF## ;SET SAMPLING INTERVAL
SETZM .CPMJ1## ;NO NEED TO STOP METER ANYMORE!
POPJ P, ;BACK TO CLOCK1
> ;END OF IFN FTRSP
SUBTTL PERF. UUO FUNCTIONS TO HANDLE KL10 PERFORMANCE METER
COMMENT &
THE KL10 PERFORMANCE METER IS ASSUMED TO BE AN INTEGRAL PART OF
THE KL10 PROCESSOR, AND THUS ITS DATA BASE IS FOUND IN THE
CDB. FOR THE PURPOSES OF DOCUMENTATION AND IN THE EVENT THAT
A FUTURE CPU CAN HAVE MORE THAN ONE TYPE OF PERFORMANCE METER,
A LIST OF THE CDB LOCATIONS USED FOR THE PERFORMANCE METER
FOLLOWS:
.CPPJB - JOB WHICH OWNS PERFORMANCE METER ON THIS CPU, 0 IF FREE
.CPMJB - JOB ENABLE CONDITION, SET BY UUO. -2 = NULL JOB, 0 = DONT CARE
.CPMJ1 - JOB ENABLE CONDITION, ONLY SET IF METER IS RUNNING.
THIS IS THE VARIABLE WHICH CLOCK1 USES TO TURN THE
METER ON AND OFF TO SIMULATE A JOB ENABLE CONDITION.
THIS VARIABLE IS NEEDED BECAUSE THE METER CAN BE
STOPPED AND THEN STARTED WITH THE SAME JOB ENABLE
.CPPMR - SET NONZERO WHENEVER THE PERFORMANCE METER IS RUNNING
USED IN CHECKING FOR STARTING METER TWICE
.CPPAE - USED TO STORE THE PERFORMANCE ANALYSIS ENABLES FOR METER
.CPPRQ - SEMAPHORE USED IN TESTING AND GIVING METER AWAY
.CPAPS - FLAG THAT CAUSES THE PERFORMANCE METER TO BE TURNED
ON AND OFF WITH THE ACCOUNTING METER
.CPMM0
.CPMM1 - DOUBLE WORD LOCATION THAT CONTAINS THE NUMBER OF
MBOX REFERENCES WHILE METER WAS ON AND ENABLED
JOB CONDITION TERM WAS TRUE. USEFUL FOR MEASURING
CACHE HIT RATE.
THE FORMAT OF THESE METER FUNCTIONS WAS SETUP TO ACCOMODATE FUTURE
METERS IF NECESSARY: EVERY ENABLE CONDITION IS A SEPARATE WORD.
THE ORDER OF THE ENABLES WERE SPECIALLY CHOSEN SUCH THAT THE
MOST FREQUENTLY USED ENABLES ARE FIRST. SINCE UNSPECIFIED ARGUMENTS
ALWAYS DEFAULT TO ZERO, THIS SAVES SPACE IN THE USER PERFORMANCE
PROGRAM.
INSTEAD OF CHECKING FOR TERMINATION OF THE ARGUMENT LIST EVERY TIME
A WORD IS FETCHED OR STORED IN THESE ROUTINES, THE SPECIAL ROUTINES
PF?WDU, PF?WD1 (?=G, GET OR P,PUT) ARE USED, WHICH RETURN 0 (DONT CARE)
ON GETTING AFTER ARGS ARE EXHAUSTED OR ARE NOOPS WHEN AN ATTEMPT IS MADE
BY THE FUNCTION ROUTINES TO PLACE A VALUE BEYOND THE LIMIT OF WHAT
THE CALLER ASKED FOR.
&;END OF COMMENT
;THE FOLLOWING PERF. UUO FUNCTIONS ARE IN KLSER:
;THE FOLLOWING ERROR ROUTINES ARE CALLED BY PERF. UUO FUNCTIONS
; IN KLSER, AND ARE FOUND IN UUOCON
;FUNCION 1 - GET METER AND SETUP METER CONDITIONS
;
;FORMAT OF ARGUMENT BLOCK:
;
;ADDR: ;NUMBER OF WORDS FOLLOWING
;ADDR+1: ;CPU TYPES (1B0=PDP6,1B1=KA10,ETC.)
;ADDR+2: ;CPU NUMBER,,MODE
;ADDR+3: ;CACHE ENABLES
;ADDR+4: ;PI CHANNEL ENABLES
;ADDR+5: ;PC ENABLES
;ADDR+6: ;MICROCODE ENABLES
;ADDR+7: ;PROBE ENABLES
;ADDR+10: ;JOB
;ADDR+11: ;RH20 CHANNEL ENABLES
;ZERO ALWAYS INDICATES DON'T CARE. FOR DETAILS ON WHAT THE
; ENABLE BITS ARE, REFER TO KL10 INTERNAL CLOCK SUPPORT FUNCTIONAL SPEC.
PMRSET::PUSHJ P,CHKPMS ;CHECK CPU TYPE STUFF AND SETUP P4
POPJ P, ;ERROR OF SOME SORT (SEE CHKPMS)
PUSHJ P,GETPMR ;GET METER
JRST PREMIU## ;**METER BUSY**
; PUSHJ P,ONCPP4 ;RESCHEDULE TO CPU IN P4
PUSHJ P,STPPMJ ;STOP METER
TRZE T4,1B35 ;T4 HAS EVENT/DURATION STATE.
;TEST BORROWED BIT (CLEAR/DON'T CLEAR)
PUSHJ P,CLRPMR ;ZERO OUT PERFORMANCE COUNT
;CACHE ENABLES
PUSHJ P,PFGWD1 ;GET CACHE ENABLES FROM USER
SKIPN T1 ;DON'T CARE??
TLO T4,(PE.CCI) ;YES, SET CACHE DON'T CARE
TLZE T1,(1B4) ;ACCOUNTING METER/PERFORMANCE METER SYNC BIT?
SETOM .CPAPS## ;YES, SET THE FLAG
LSH T1,<-<^L<PE.CCR>>-<^D18>> ;SHIFT INTO POSITION
TRC T1,(PE.CCR!PE.CCF!PE.EWB!PE.SWB) ;ACCOUNT FOR THE FACT
; THAT THESE BITS ARE ZERO WHEN THE
;CONDITION IS ENABLED!
ANDI T1,(PE.CCR!PE.CCF!PE.EWB!PE.SWB) ;PREVENT OTHER BITS FROM SETTING
TSO T4,T1 ;SET DESIRED BITS
;PI ENABLES
PUSHJ P,PFGWD1 ;GET PI ENABLES
SKIPN T1 ;DON'T CARE??
TRO T4,PE.PPI ;PI IGNORE IF ZERO ARG
LSH T1,<-<^L<PE.PP0>>> ;SHIFT INTO POSITION
ANDI T1,PE.PPI ;CLEAR OUT ERRONEOUS BITS
TDO T4,T1 ;AND SET THEM IN T4
;PC ENABLES
PUSHJ P,PFGWD1 ;GET THEM
TLCE T1,(1B0!1B1) ;IF ALL BITS ARE ZERO OR
TLNN T1,(1B0!1B1) ;IF BOTH ARE SET
TRO T4,PE.PCI ;SET PC IGNORE
TLNN T1,(1B0) ;IN ANY CASE, WANT USER PC?
TRO T4,PE.PCU ;YES,SET PC USER (NN BECAUSE BITS ARE COMP.)
;MICROCODE ENABLES
PUSHJ P,PFGWD1 ;GET UCODE ENABLES
TLNN T1,(1B0) ;SKIP IF UCODE STATE ENABLED
TLO T4,(PE.UCI) ;NOT ENABLED, SET UCODE IGNORE BIT
;PROBE ENABLES
PUSHJ P,PFGWD1 ;GET THEM
TLCE T1,(1B0!1B1) ;IF BOTH OFF OR
TLNN T1,(1B0!1B1) ;BOTH ON
TLO T4,(PE.PRI) ;IGNORE PROBE
TLNN T1,(1B0) ;IN ANY CASE, WANT PROBE LOW? (COMP)
TLO T4,(PE.PRL) ;YES, ENABLE PROBE LOW
;JOB ENABLE
PUSHJ P,PFGWD1 ;JOB ENABLE
JUMPE T1,PMRST1 ;IGNORE IS OK
CAMN T1,[-1] ;SELF?
MOVE T1,J ;YES
CAMN T1,[-2] ;NULL JOB?
JRST PMRST1 ;YES, DON'T CALL LGLPRC
PUSHJ P,LGLPRC## ;IS THIS A LEGAL NUMBER?
JRST PREBJN## ;BAD JOB NUMBER
PMRST1: MOVEM T1,.CPMJB## ;EVERYTHING'S OK, STORE JOB ENABLE
;NOW FOR CHANNEL ENABLES
PUSHJ P,PFGWD1 ;GET THEM
SKIPN T1 ;DON'T CARE?
TLO T4,(PE.CPI) ;YES, SET ALL BITS FOR DON'T CARE
LSH T1,<-<^L<PE.CP0>>-<^D18>> ;POSITION (IN RH)
ANDI T1,PE.PPI ;CLEAR UNWANTED BITS
TSO T4,T1 ;AND SET THE BITS
;ADD FURTHER ENABLE LOGIC HERE
MOVEM T4,.CPPAE## ;AT LAST
JRST CPOPJ1## ;BYE.
;FUNCTION 2 - START METER
;
;THE METER MUST BE OWNED BY THE CALLING JOB (CHECKED BY PRFCPU).
; SPECIAL CARE IS TAKEN NOT TO START THE METER IF THE CALLING JOB DOES NOT
;SATISFY THE JOB ENABLE CONDTION. AFTER THE METER IS STARTED,
; THE FUNCTION RETURNS THE DOUBLE WORD TIME BASE AND PERFORMANCE COUNT
; IN THE ARGUMENT BLOCK, WHICH HAS THE FOLLOWING FORMAT:
;
;ADDR: ;COUNT OF WORDS FOLLOWING
;ADDR+1: ;CPU NUMBER
;ADDR+2: ;HIGH ORDER TIME BASE RETURNED HERE
;ADDR+3: ;LOW ORDER TIME BASE RETURNED HERE
;ADDR+4: ;HIGH ORDER PERFORMANCE METER VALUE
;ADDR+5: ;LOW ORDER " "
;ADDR+6: ;HIGH ORDER MBOX REFERENCE COUNT
;ADDR+7: ;LOW ORDER MBOX REFERENCE COUNT
PMRSTR::PUSHJ P,PRFCPU ;CHECK CPU SPEC, SETUP P4, MAKE SURE METER IS OWNED
POPJ P, ;SORRY, SOMETHING WENT WRONG
SKIPE .CPPMR## ;SKIP IF METER IS NOT STARTED ALREADY
JRST PREMAS## ;**METER ALREADY STARTED**
; PUSHJ P,ONCPP4 ;MUST RESCHEDULE ON THE RIGHT CPU TO START METER
CONO PI,PI.OFF ;TURN OFF PI SO WE CAN START AND READ
;METER WITHOUT INTERRUPTIONS
PUSHJ P,STRPMJ ;START METER IF WE'RE SUPPOSED TO
;FALL INTO STORPT
STORPT: PUSHJ P,REDPMT ;READ TIME BASE AND PERF METER INTO T1-T4
PUSH P,.CPMM1## ;ALSO SAVE MEMORY REFERENCE COUNT BEFORE
PUSH P,.CPMM0## ; PI SYSTEM IS TURNED BACK ON
CONO PI,PI.ON ;TURN PI BACK ON
PUSHJ P,PFPWD1 ;STORE HIGH ORDER TIME BASE
MOVE T1,T2
PUSHJ P,PFPWD1 ;STORE LOW ORDER TIME BASE
MOVE T1,T3
PUSHJ P,PFPWD1 ;STORE HIGH ORDER PERFORMANCE COUNT
MOVE T1,T4
PUSHJ P,PFPWD1 ;STORE LOW ORDER PERF COUNT
POP P,T1 ;GET HIGH ORDER MEMORY REFERENCE COUNT BACK
PUSHJ P,PFPWD1 ;GIVE THAT TO USER
POP P,T1 ;NOW GET LOW ORDER MEM REF COUNT
AOS (P) ;GIVE SKIP RETURN
PJRST PFPWD1 ;STORE LOW ORDER MBOX COUNT AND RETURN
;FUNCTION 3 - READ PERFORMANCE METER
;
;FORMAT OF ARGUMENT LIST SAME AS FUNCTION 2, START METER
PMRRED::PUSHJ P,PRFCPU ;CHECK AND SETUP CPU STUFF, METER OWNER
POPJ P, ;SOMETHING WENT WRONG
; PUSHJ P,ONCPP4 ;RESCHEDULE ONTO PROPER CPU FOR THIS METER
PJRST STORPT ;STORE TIME BASE, PERF COUNT AND RETURN
;FUNCTION 4 - STOP METER
;
;FORMAT OF ARG LIST SAME AS START AND READ FUNCTIONS
;
PMRSTP::PUSHJ P,PRFCPU ;SETUP P4, CHECK METER OWNERSHIP
POPJ P, ;OOOPS
; PUSHJ P,ONCPP4 ;PUT OURSELVES ONTO PROPER CPU
SKIPN .CPPMR## ;IS METER RUNNING?
JRST PREMNR## ;**METER NOT RUNNING** (SO WHY STOP IT?)
PUSHJ P,STPPMJ ;STOP METER
PJRST STORPT ;STORE GOOD STUFF AND RETURN
;FUNCTION 5 - RELEASE METER
;FORMAT OF ARGUMENT BLOCK:
;
;ADDR: ;NUMBER OF WORDS FOLLOWING
;ADDR+1: ;CPU NUMBER OF METER TO RELEASE
PMRREL::PUSHJ P,PRFCPU ;GOOD CPU? THEN SETUP P4 AFTER WE KNOW WE OWN METER
POPJ P, ;SORRY CHARLIE
; PUSHJ P,ONCPP4 ;RESCHEDULE ONTO PROPER CPU
PUSHJ P,STPPMJ ;STOP METER
MOVE T1,.CPSLF## ;POINT T1 AT THIS CPU'S CDB
AOS (P) ;SET FOR SKIP RETURN
PJRST RELPMR ;AND RELEASE, RETURN
;FUNCTION 6 - TURN OFF BACKGROUND PERFORMANCE ANALYSIS
;FUNCTION 7 - TURN ON BACKGROUND PERFORMANCE ANALYSIS
;FORMAT OF ARGUMENT BLOCK:
;
;ADDR: ;NUMBER OF WORDS FOLLOWING
;ADDR+1: ;CPU TYPES
;ADDR+2: ;CPU NUMBER,,MODE (1B19 = CLEAR COUNTS)
;ADDR+3: ;SAMPLING INTERVAL (CLOCK TICKS PER SAMPLE ITEM)
IFN FTRSP,< ;ONLY IF RESPONSE NUMBERS WANTED
PMRBPF::PUSHJ P,CHKPMS ;VERIFY AND GET TO CPU DESIRED
POPJ P, ;SOMETHING DIDN'T MAKE IT
SETZM .CPBPF## ;CLEAR CLOCK-LEVEL COUNTER
JRST CPOPJ1## ;SUCCESSFUL RETURN
PMRBPN::PUSHJ P,CHKPMS ;VERIFY AND GET TO CPU DESIRED
POPJ P, ;SOMETHING DIDN'T MAKE IT
SETZM .CPBPF## ;AVOID CLOCK-LEVEL RACE
TRNN T4,1B35 ;USER WANT TO "CLEAR" THE COUNTER(S)?
JRST PMBPN2 ;NO, ACCUMULATE SYSTEM TOTALS
SETZM .CPBPV## ;YES, CLEAR FIRST WORD OF BPA BLOCK
MOVE T1,[.CPBPV##,,.CPBPV##+1] ;BLT POINTER TO
BLT T1,.CPBPV##+<BPATLN##*4>-1 ;CLEAR OUT ALL OF THE BPA BLOCK
PMBPN2: PUSHJ P,PFGWD1 ;GET SAMPLING INTERVAL
CAIG T1,0 ;USEFUL NUMBER SUPPLIED?
MOVE T1,.CPBPC## ;NO, USE LAST SPECIFIED FOR THIS CPU
CAIG T1,0 ;USEFUL NUMBER YET?
MOVEI T1,3 ;NO, SET INTERVAL TO 3 TICKS
MOVEM T1,.CPBPC## ;TELL BPAUPD HOW LONG TO SAMPLE EACH ITEM
SETZM .CPBPI## ;TELL BPAUPD TO RE-INITIALIZE ITSELF
SETOM .CPBPF## ;TELL CLOCK-LEVEL TO START UP BPAUPD
JRST CPOPJ1## ;RETURN SUCCESSFULLY
> ;END OF IFN FTRSP
;ROUTINE TO CHECK INITAL CPU/METER SPECIFICATION
; CALL WITH M SETUP TO POINT TO ADDRESS BEFORE CPU TYPE WORD.
; SMASHES T1-T3, RETURNS T4 WITH EVENT MODE BIT EITHER SET OR CLEAR
; DEPENDING ON THE MODE ARGUMENT THE CALLER SUPPLIES.
; THIS ROUTINE ALSO BORROWS BIT 35 TO INDICATE WHETHER OR NOT THE
; PERFORMANCE METER COUNT SHOULD BE CLEARED OR NOT. THIS BIT
; SHOULD BE CLEARED IMMEDIATELY AFTER CHECKING, SINCE IT MIGHT
; BE USED BY THE HARDWARE
;
;AN ERROR RETURN IS GIVEN FROM THIS ROUTINE IF THE CPU SPECIFICATION
; IS INCORRECT OR A CPU NUMBER CORRESPONDING TO A NON-EXISTANT CPU IS GIVEN.
; THE CALLER MUST ACTUALLY GET CONTROL OF THE METER.
CHKPMS: PUSHJ P,PFGWD1 ;GET CPU TYPES ACCEPTABLE
MOVE T3,T1 ;SAVE IN T3
PUSHJ P,PFGWD1 ;GET CPU NUMBER,,MODE
TLNN T3,(1B3) ;CPU TYPE MUST BE KL10 FOR THIS FUNCTION
JRST PREICT## ;**IMPROPER CPU TYPE**
SETZ T4, ;START WITH ZERO FOR PERFORMANCE ENABLE WORD
TRNN T1,1B18 ;SKIP IF NOT EVENT MODE
MOVEI T4,PE.EVM ;IS EVENT MODE, SET THE BIT
TRNE T1,1B19 ;CLEAR METER COUNT?
TRO T4,1B35 ;YES, BORROW A BIT TO TELL ABOUT IT
HLRZS T1
CAILE T1,CPUN##-1
JRST PRENXC##
IFN FTMP,<
PUSHJ P,ONCPUS##
JRST PRENXC##
>
PJRST CPOPJ1## ;AND GIVE SKIP RETURN
;THIS ROUTINE IS USED IN THE START, READ, STOP, AND RELEASE ROUTINES.
; IT CHECKS THE CPU NUMBER FOR LEGALITY, AND GIVES ERROR RETURN IF
; CPU NUMBER IS BAD. IT ALSO GIVES AN ERROR RETURN IF
; THE CALLER (WHOSE JOB IS IN AC J) DOES NOT OWN THE METER.
; THIS ROUTINE DISTINGUISHES BETWEEN THE CASES OF METER IN USE
; AND METER NOT SETUP WHEN IT DISCOVERS THAT THE CALLER DOES NOT
; OWN THE METER. M SHOULD BE SETUP TO POINT TO THE ITEM COUNT
; OF THE ARG BLOCK. AC'S T3-T4 ARE PRESERVED. P4 IS SETUP TO BE
; THE CPU DATA BLOCK OF THE SPECIFIED CPU.
PRFCPU: PUSHJ P,PFGWD1 ;GET CPU NUMBER
MOVEI T2,CPUN##
CAIGE T2,1(T1)
JRST PRENXC##
IFN FTMP,<
PUSHJ P,ONCPUS##
JRST PRENXC##
>
CAMN J,.CPPJB##
JRST CPOPJ1## ;YES, RETURN
SKIPE .CPPJB## ;IS METER OWNED BY SOMEONE ELSE??
JRST PREMIU## ;**METER IN USE**
JRST PREMNS## ;**METER NOT SETUP**
;SPECIAL ROUTINES TO PICK UP ARGUMENTS FOR PERFORMANCE METER FUNCTIONS.
; IF THE COUNT GIVEN BY THE CALLER (IN P2) IS EXHAUSTED, THE PUTTER
; ROUTINE DOES NOTHING AND THE GETTER ROUTINE RETURNS A ZERO
; (DON'T CARE). THIS SAVES SOME CHECKING ELSEWHERE.
PFPWD1: SOJL P2,CPOPJ## ;IF COUNT IS GONE, DO NOTHING
PJRST PUTWD1## ;ELSE DO PUTWD1
PFGWD1: SETZ T1, ;CLEAR T1 IN CASE COUNT IS GONE
SOJL P2,CPOPJ## ;RETURN ZERO IF COUNT EXHAUSTED
PJRST GETWD1## ;ELSE DO GETWD1
;ROUTINE TO READ IN TIME BASE AND PERFORMANCE METER COUNT AT THE
; SAME TIME, MAKING SURE NO INTERRUPTS INTERFERE.
;
;RETURNS TIME BASE HI AND LO IN T1,T2 AND PERF COUNT IN T3,T4
;
;MUST BE ON CPU OF TARGET METER - CALLER'S RESPONSIBILITY
;
;PRESERVES P AC'S, T1-T4 ARE DESTROYED
REDPMT::CONSO PI,PI.IPA ;PI OFF ALREADY?
JRST REDPM2 ;YES, DON'T TURN IT ON AGAIN
PUSHJ P,REDPM1 ;NO, TURN IT ON AFTER WERE THROUGH
PJRST ONPOPJ##
REDPM1: SYSPIF ;TURN OFF PI
REDPM2: RDTIME T1 ;HI AND LO INTO T1,T2
RDPERF T3 ;HI AND LO PERF INTO T3,T4
POPJ P, ;RETURN
;ROUTINE TO START PERFORMANCE METER USED BY PERF. UUO
; SETS UP JOB CONDITION FOR CLOCK1 AND THEN USES SCDPR1
; TO START THE METER IF THE JOB ENABLE CONDITION IS SATISFIED.
; PRESERVES ALL AC'S EXECPT T1. MUST BE CALLED ON CPU OF DESIRED METER,
; PRESERVES STATE OF PI SYSTEM (ON,OFF)
STRPMJ::PUSH P,.CPMJB## ;PUT METER ENABLE INTO
POP P,.CPMJ1## ;PROPER WORD
SETOM .CPPMR## ;SAY THAT METER IS RUNNING
PJRST SCDPR1 ;START METER IF WE'RE SUPPOSED TO AND RETURN
;ROUTINE TO START PERFORMANCE METER USED BY CLOCK1, CALLED BY STRPMJ.
; THIS ROUTINE ACTUALLY STARTS THE PERFORMANCE METER ACCORDING TO
; THE CONDITIONS IN .CPPAE. PRESERVES ALL AC'S, STATE OF PI SYSTEM.
; CALL WITH P4 = CPU DATA BLOCK, MUST BE ON CPU OF TARGET METER.
STRPMR::WRPAE .CPPAE## ;THIS IS ALL THAT'S NECESSARY
POPJ P, ;THERE, THAT WAS EASY
;ROUTINE TO STOP METER USED BY PERF UUO.
; STOPS METER AND CLEARS JOB ENABLE FLAG FOR CLOCK1 SO IT DOESN'T
; TURN THE METER ON. USES ACS T1,T2. PRESERVES STATE OF PI SYSTEM.
; CALL ON CPU OF TARGET METER WITH P4 = CPU DATA BLOCK
STPPMJ::PUSHJ P,CHKPMJ ;WERE WE PART OF THE JOB ENABLE CONDITION?
JRST STPPJ1 ;NO, DON'T UPDATE MBOX REFERENCE COUNT
PUSHJ P,GETMBT ;GET MBOX REFERENCES IN T1,T2
DADD T1,.CPMM0## ;UPDATE COUNT
DMOVEM T1,.CPMM0##
STPPJ1: SETZM .CPMJ1## ;CLEAR JOB ENABLE THAT CLOCK1 LOOKS AT
SETZM .CPPMR## ;AND SAY THAT METER IS NOW STOPPED
; PJRST STPPMR ;STOP METER AND RETURN
;ROUTINE TO STOP PERF METER. DOESN'T TOUCH JOB ENABLE, SO CLOCK1
; CAN CALL IT TO START AND STOP METER FOR JOB ENABLE LOGIC.
; PRESERVES ALL AC'S, STATE OF PI SYSTEM. CALL ON CPU OF TARGET METER
; WITH P4 SETUP ACCORDINGLY.
STPPMR::WRPAE [0] ;ZERO STOPS THE METER
POPJ P, ;ANOTHER COMPLICATED ROUTINE
;ROUTINE TO GET THE PERFORMANCE METER USED BY PERF. UUO
; CALL WITH JOB NUMBER OF CALLER IN J, ADDRESS OF CPU DATA
; BLOCK OF CPU OF TARGET METER IN P4. MUST BE ON THE
; CPU OF TARGET METER. NON-SKIP RETURN IF METER IS ALREADY IN
; USE, SKIP RETURN IF ALREADY OWN METER OR METER WAS FREE.
GETPMR: CAMN J,.CPPJB## ;ALREADY OWN IT?
JRST CPOPJ1## ;YES, GOOD RETURN
AOSE .CPPRQ## ;AVAILABLE?
POPJ P, ;NO, NOT NOW.
MOVEM J,.CPPJB## ;YES, PUT OUR NAME ON THE METER
; NOTE THIS WILL ALSO TURN OFF ANY
; BACKGROUND PERF ANALYSIS PENDING
JRST CPOPJ1## ;GOOD RETURN
;ROUTINE TO RELEASE PERFORMANCE METER USED BY PERF. UUO AND
; EMERGENCY ROUTINES (RESET, SWAP READ ERROR, ETC.)
; CALL WITH P4 = CPU DATA BLOCK OF TARGET PERF METER. NEED NOT
; BE RUNNING ON TARGET CPU (SO SWAPPER CAN CALL, RESET, ETC.)
; CLEARS ALL METER VARIABLES FOR SPECIFIED CPU.
; ALL AC'S PRESERVED.
RELPMR: SETZM .CPAPS##-.CPCDB##(T1) ;CLEAR PERF/ACC METER SYNC FLAG
SETZM .CPMJB##-.CPCDB##(T1) ;CLEAR MEASURED JOB
SETOM .CPMJ1##-.CPCDB##(T1) ;-1 IS FLAG FOR CLOCK1 TO STOP METER
SETZM .CPPJB##-.CPCDB##(T1) ;CLEAR OWNING JOB
SETZM .CPPAE##-.CPCDB##(T1) ;AND PERFORMANCE ENABLES
SETOM .CPPRQ##-.CPCDB##(T1) ;NOW MAKE METER AVAILABLE
SETZM .CPBPI##-.CPCDB##(T1) ;TELL BACKGROUND UPDPAC TO REINIT
SKIPLE .CPBPC##-.CPCDB##(T1) ;BACKGROUND PERF ANAL ON FOR CPU?
SETOM .CPBPF##-.CPCDB##(T1) ;YES, RESTART AT NEXT CLOCK TICK
POPJ P, ;ONLY RETURN
;(ALWAYS SUCCEEDS!)
;ROUTINE TO CLEAR PERFORMANCE METER COUNT
; USED BY PERF. UUO AT METER SETUP TIME. CALLER SHOULD
; MAKE SURE THAT IT OWNS THE METER INVOLVED.
; CALLER MUST MAKE SURE HE IS RUNNING ON CPU OF TARGET
; METER. CALLER SHOULD ALSO MAKE SURE METER IS STOPPED.
CLRPMR: WRPAE [PE.CLR] ;CLEAR HARDWARE COUNTER
MOVE T1,.CPEPT##
SETZM .E0HPA##-.E0MP##(T1) ;CLEAR HI PERF COUNT
SETZM .E0LPA##-.E0MP##(T1) ;AND LO
SETZM .CPMM0## ;CLEAR OUT MBOX COUNT ALSO
SETZM .CPMM1## ;HIGH AND LOW ORDERS
POPJ P, ;RETURN
;ROUTINE CALLED AFTER SCHEDULER IN CLOCK1 TO IMPLEMENT JOB ENABLE CONDITION.
; .CPMJ1 CONTAINS THE ENABLE CONDITION. -2 IS NULL JOB, -1 IS A SPECIAL
; CODE MEANING STOP THE METER (USED IF A RESET IS DONE BEFORE METER
; IS RELEASED), 0 MEANS THE JOB ENABLE IS DON'T CARE, AND NON-ZERO
; MEANS LEAVE THE METER RUNNING IF AND ONLY IF THE JOB NUMBER
; IN .CPMJ1 IS ABOUT TO BE RUN. ALL ACS PRESERVED.
SCDPMR::PUSH P,T1 ;SAVE T1
PUSHJ P,SCDPR1 ;CALL THE ROUTINE
JRST TPOPJ## ;RESTORE T1 AND RETURN
SCDPR1: MOVE T1,.CPMJ1## ;GET JOB ENABLE CONDITION
AOJE T1,STPPMJ ;IT WAS A REQUEST TO STOP METER, DO IT.
SKIPN .CPPJB## ;METER OWNED BY ANYONE?
POPJ P, ;NO, LEAVE THE METER ALONE
PUSHJ P,CHKPMJ ;CHECK THE JOB ENABLE CONDITION.
PJRST STPPMR ;NOT SATISFIED, STOP THE CLOCK
PJRST STRPMR ;IS SATISFIED, START UP THE CLOCK, EVEN
;THOUGH IT MAY BE STARTED ALREADY (SO WHAT)
;ROUTINE TO CHECK ON THE JOB ENABLE CONDITION.
; CALL WITH JOB NUMBER TO BE TESTED IN J, CPU DATA BLOCK ADDR IN P4.
; GIVES SKIP RETURN IF THE JOB IN J CAUSES THE CPU ENABLE CONDITION
; FOR THE PERFORMANCE METER TO BE SATISFIED, NON-SKIP IF THE CONDITION
; IS NOT SATISFIED OR SOMEONE IS TRYING TO STOP THE METER (-1 IN .CPMJ1).
;USES T1.
CHKPMJ::SKIPN T1,.CPMJ1## ;GET JOB ENABLE. IS IT ZERO?
JRST CPOPJ1## ;YES, CONDITION IS DON'T CARE, GIVE SKIP RETURN
CAMN J,T1 ;NO, DOES .CPMJ1 CONTAIN JOB NUMBER WHICH
; IS IN J?
JRST CPOPJ1## ;YES, GIVE SKIP RETURN
AOJGE T1,CPOPJ## ;IF T1 = -1, SOMEONE WANTS METER STOPPED.
; CALLER'S RESPONSIBILITY TO STOP IT
; IF T1 WAS .GT. ZERO, CONDITION FOR JOB IS NOT MET, SO
; GIVE NON-SKIP RETURN
PJUMPE J,CPOPJ1## ;JOB ENABLE MUST HAVE BEEN NULL JOB.
; IF J .EQ. 0, ENABLE CONDITION IS SATISFIED.
POPJ P, ;SORRY, CONDITION NOT SATISFIED
;ROUTINE TO GIVE UP THE PERFORMANCE METER ON THE CPU'S THIS JOB OWNS IT ON
GIVPMR::MOVEI T1,.C0CDB## ;START WITH CPU0
GIVPM1: CAMN J,.CPPJB##-.CPCDB##(T1) ;OWN THE PERFORMANCE METER ON THIS CPU?
PUSHJ P,RELPMR ;YES, RELEASE IT
HLRZ T1,.CPCDB##-.CPCDB##(T1) ;NEXT CPU
JUMPN T1,GIVPM1 ;JUMP IF ALL CPU'S HAVEN'T BEEN CHECKED
POPJ P, ;RETURN
SUBTTL SET CACHE STRATEGY
;ROUTINE CALLED TO SET KL CACHE STRATEGY AS SPECIFIED TO KLI.
;SETS/CLEARS LG.CSL!LG.CSW IN .CPEBR AS APPROPRIATE, PRINTS A
;WARNING MESSAGE ON THE CTY IF CACHE WAS DISABLED.
SETCSH::PUSHJ P,SPCGSF## ;GET SECONDARY PROTOCOL FLAG WORD
TRNN T1,DF.CSH ;DID OPERATOR SPECIFY TO ENABLE CACHE?
SKIPA T1,[ANDCAB T2,.CPEBR##] ;NO, GET CLEAR INSTRUCTION
MOVE T1,[IORB T2,.CPEBR##] ;YES, GET SET INSTRUCTION
MOVEI T2,LG.CSL!LG.CSW ;GET THE CACHE STRATEGY BITS
XCT T1 ;SET/CLEAR IN .CPEBR AS APPROPRIATE
TRNE T2,LG.CSL!LG.CSW ;CACHE STRATEGY OFF?
POPJ P, ;NO, NOTHING TO WARN
PUSHJ P,CTYERM## ;SET FOR OUTPUT TO CTY
MOVEI T1,[ASCIZ /
%% Cache is disabled/]
PUSHJ P,CONMES## ;START MESSAGE
MOVEI T1,M.CPU## ;GET NUMBER OF CPUS IN THIS MONITOR
SOJE T1,PCRLF## ;DON'T PRINT CPUN IF THERE'S ONLY ONE
MOVEI T1,[ASCIZ / on /] ;SEPARATOR
PUSHJ P,CONMES## ;PRINT IT
MOVE T2,.CPLOG## ;GET THE CPU NAME
PUSHJ P,PRNAME## ;PRINT IT
PJRST PCRLF## ;PRINT CR-LF AND RETURN
SUBTTL OINKSR - KL10 MODULE TO SUPPORT G-FLOATING INSTRUCTIONS
Comment @
This module simulates some G-floating conversion instructions which
the KL-10 uCode does not presently handle. At one time, the uCode
did handle these, but we reclaimed the uCode space for other fixes.
The instructions currently handled are:
DGFIX
GFIX
DGFIXR
GFIXR
which are all EXTEND opcodes.
This code is ripped off from the TOPS-20 module APRSRV, and should be kept
in sync; If this code is changed, Please change the tops-20 code also.
@
OPDEF CALL [PUSHJ P,0] ;CALL
OPDEF RET [POPJ P,0] ;RETURN
.NODDT CALL,RET
GFLT%O==1B1 ;GFLOAT OVERFLOW FLAG
GFLT%2==1B2 ;GFLOAT TWO AC STORE FLAG
PC%TP1==1B10 ;TRAP 1. USED ONLY BY GFLOAT
OPDEF DGFIX [023000,,0] ;GFLT TO DOUBLE INTEGER
OPDEF GFIX [024000,,0] ;GFLT TO INTEGER
OPDEF DGFIXR [025000,,0] ;GFLT TO DOUBLE INTEGER ROUNDED
OPDEF GFIXR [026000,,0] ;GFLT TO INTEGER ROUNDED
OINKSR:: ;[TOPS10]
GFLT0: ;HERE TO CHECK FOR GFLT'S
PUSHJ P,GETWDU## ;GET THE EXTEND OPCODE
LDB T3,[POINT 9,T1,8];GET THE EXTENDED OPCODE
CAIL T3,<<DGFIX>_-^D27>;IS IT A GFLT INSTRUCTION?
CAILE T3,<<GFIXR>_-^D27>
JRST ILLIN1## ;NO, GIVE HIM AN ILL UUO
SUBI T3,<<DGFIX>_-^D27>;CONVERT TO GFLTD OFFSET
PUSHJ P,GFLTXX ;DISPATCH TO WORKER ROUTINES
TLNE T4,(GFLT%O) ;DID IT OVERFLOW
JRST GFLT1 ;YES...GO HANDLE IT
LDB T3,[POINT 4,.USMUO,30] ;GET THE AC THE USER USED
UMOVEM T1,(T3) ;SAVE THE FIRST AC
TLNN T4,(GFLT%2) ;IS IT A TWO AC RESULT?
JRST USRXIT## ;NO...SO WE ARE DONE
ADDI T3,1 ;YES...SO BUMP THE AC VALUE
ANDI T3,17 ;MAKE ADDITION MODULO 16
UMOVEM T2,(T3) ;SAVE THE SECOND AC RESULT
JRST USRXIT## ;RETURN TO USER
GFLT1:
MOVSI T1,(XC.OVF!PC%TP1);CAUSE AN OVERLOW TRAP.
IORM T1,.JDAT+JOBPD1##;BY CHANGING THE USER FLAGS.
JRST USRXIT## ;AND RETURN
GFLTD: IFIW .DGFX ;DGFIX
IFIW .GFX ;GFIX
IFIW .DGFXR ;DGFIXR
IFIW .GFXR ;GFIXR
GFLTXX: PUSH P,GFLTD(T3) ;PUSH DISPATCH TO ROUTINE
TLZ T1,777740 ;TURN OFF EVERYTHING EXCEPT I,X,AND Y
PUSHJ P,EACALC## ;CHECK FOR POSSIBLE INDIRECT AND INDEXING
JRST UADERR## ;GIVE AN ADDRESS CHECK
MOVE M,T1 ;COPY POINTER
PUSHJ P,GETWDU## ;GET FIRST WORD OF PAIR
PUSH P,T1 ;SAVE FOR A WHILE
PUSHJ P,GETWD1## ;GET SECOND WORD OF PAIR
MOVE T2,T1 ;MAKE IT SECOND WORD OF PAIR
POP P,T1 ;GET BACK FIRST WORD OF PAIR
SETZ T4, ;CLEAR ALL FLAGS.
POPJ P, ;GO TO WORKER ROUTINE BY POPPING
COMMENT @
***********************************
***** N N OOO TTTTT EEEEE *****
***** NN N O O T E *****
***** N N N O O T EEE *****
***** N NN O O T E *****
***** N N OOO T EEEEE *****
***********************************
The following routines are copied verbatim from TOPS20 APRSRV. If either
changes, please update the other.
@
.DGFXR: ;GFLT TO DOUBLE INTEGER ROUNDED
MOVSI T4,(GFLT%2) ;SET THE DOUBLE AC FLAG
CALL DGFXR0 ;GO TO COMMON CODE
JUMPG T3,DGFXR1 ;IF SHIFT POSITIVE THEN SHIFT LEFT
CAMG T3,[-^D70] ;SHIFT INSTS ARE MOD 256 SO REDUCE
MOVNI T3,^D70 ;EXPONENT IF ITS TOO LARGE
ASHC T1,1(T3) ;SHIFT ROUNDING BIT INTO RIGHTMOST OF T2
DADD T1,[EXP 0,1] ;ROUND
ASHC T1,-1 ;SHIFT ROUNDING BIT OUT
RET ;RETURN TO CALLER
DGFXR1: CAILE T3,^D11 ;CHECK EXPONENT SIZE
JRST DGFXR3 ;TOO BIG THEN OVERFLOW
DGFXR2: ASHC T1,(T3) ;SHIFT LEFT NO ROUNDING
RET ;RETURN TO CALLER
DGFXR3: CAIN T3,^D12 ;CHECK FOR LARGEST NEGATIVE INTEGER
JUMPL T1,[CAMN T1,[777740000000]
JUMPE T2,DGFXR2 ;LET THAT ONE THROUGH
JRST .+1] ;OVERFLOW ON ALL OTHERS
DGFXR4: TLO T4,(GFLT%O) ;SET THE OVERFLOW FLAG
RET ;AND RETURN TO CALLER
DGFXR0: ;COMMON CODE FOR DGFIXR AND DFIXR
LDB T3,[POINT 11,T1,11];GET THE EXPONENT
TLNE T1,(1B0) ;PROPAGATE SIGN THROUGH EXPONENT BITS
TLOA T1,777700 ;NEGATIVE SET TO ONES
TLZA T1,777700 ;POSITIVE SET TO ZEROES
TRC T3,3777 ;UNCOMPLEMENT EXPONENT IF NEGATIVE
SUBI T3,2000+^D59 ;GET SHIFT VALUE TO ALIGN INTEGER PART
RET ;RETURN TO CALLER
.GFXR: ;GFLOAT TO SINGLE INTEGER ROUNDED
SETZ T4, ;RESET FLAG AC
CALL DGFXR0 ;GO TO COMMON CODE
JUMPG T3,DFXR1 ;IF SHIFT COUNT POSITIVE GO SHIFT LEFT
CAMG T3,[-^D70] ;SHIFT INSTS ARE MOD 256 SO REDUCE
MOVNI T3,^D70 ;NEW EXPONENT IF IT WAS TOO LARGE
ASHC T1,1(T3) ;SHIFT ROUNDING BIT INTO T2
DADD T1,[EXP 0,1] ;ROUND
ASHC T1,-1 ;SHIFT ROUNDING BIT OUT
JRST DFXR3 ;GO CONVERT TO SINGLE INTEGER
DFXR1: CAILE T3,^D11 ;CHECK EXPONENT SIZE
JRST DGFXR4 ;GO DO OVERFLOW STUFF
DFXR2: ASHC T1,(T3) ;SHIFT LEFT NO ROUNDING NEEDED
DFXR3: CAME T1,[-1] ;HIGH WORD MUST BE ALL SIGN BITS
JUMPN T1,DGFXR4 ;IF IT ISNT THEN OVERFLOW
MOVE T1,T2 ;GET WORD INTO CORRECT AC
RET ;RETURN TO CALLER
.GFX: ;GFLOAT TO SINGLE INTEGER
SETZ T4, ;RESET FLAG AC
PUSH P,T1 ;SAVE ORIGINAL SIGN
SKIPGE T1 ;IS NUMBER POSITIVE?
DMOVN T1,T1 ;NO...GET ABSOLUTE VALUE
LDB T3,[POINT 11,T1,11];GET THE EXPONENT
TLZ T1,777700 ;CLEAR EXPONENT FROM NUMBE
SUBI T3,2000+^D59 ;GET SHIFT AMOUNT TO ALIGN INTEGER PART
CAMG T3,[-^D70] ;SHIFT INSTS ARE MOD 256 SO REDUCE
MOVNI T3,^D70 ;EXPONENT IF ITS LARGE
CAILE T3,^D11 ;CHECK EXPONENT SIZE
JRST GFX2 ;TOO BIG...OVERFLOW
ASHC T1,(T3) ;SHIFT FRACTION OFF
SKIPGE 0(P) ;CHECK ORIGINAL SIGN
DMOVN T1,T1 ;IF NEGATIVE COMPLEMENT RESULT
TLNE T1,(1B0) ;COPY HIGH SIGN INTO LOW WORD
TLO T2,(1B0)
CAME T1,[-1] ;HIGH WORD MUST BE ALL SIGN BITS
JUMPN T1,GFX2 ;ELSE OVERFLOW
MOVE T1,T2 ;PUT RESULT INTO PROPER AC FOR RETURN
GFX1: ADJSP P,-1 ;FIX STACK
RET ;AND RETURN TO CALLER
GFX2: TLO T4,(GFLT%O) ;HERE ON OVERFLOW...SET THE FLAG
JRST GFX1 ;AND RETURN TO USER
.DGFX: ;GFLOAT TO DOUBLE INTEGER
MOVSI T4,(GFLT%2) ;SET THE TWO ACS FLAG
PUSH P,T1 ;SAVE THE ORIGINAL SIGN
JUMPGE T1,DGFX1 ;IS NUMBER POSITIVE?
DMOVN T1,T1 ;NO...SO GET ABSOLUTE VALUE
CAMN T1,[210740000000];CHECK FOR -2^70
JUMPE T2,DGFX5 ;IT IS SPECIAL SO HANDLE IT
DGFX1: LDB T3,[POINT 11,T1,11];GET THE EXPONENT
TLZ T1,777700 ;CLEAR THE EXPONENT FIELD
SUBI T3,2000+^D59 ;GET SHIFT AMOUNT TO ALIGN INTEGER PART
CAMG T3,[-^D70] ;SHIFT INSTS ARE MOD 256
MOVNI T3,^D70 ;REDUCE EXPONENT IF IT IS LARGE
CAILE T3,^D11 ;CHECK EXPONENT SIZE
JRST DGFX4 ;TOO BIG SO OVERFLOW
ASHC T1,(T3) ;SHIFT FRACTION OFF
SKIPGE 0(P) ;CHECK ORIGINAL SIGN
DMOVN T1,T1 ;IF NEGATIVE THEN COMPLEMENT
TLNE T1,(1B0) ;COPY HIGH SIGN INTO LOW WORD
TLO T2,(1B0)
DGFX2: ADJSP P,-1 ;FIX UP THE STACK
RET ;AND RETURN TO CALLER
DGFX4: TLO T4,(GFLT%O) ;SET THE OVERFLOW FLAG
JRST DGFX2 ;AND RETURN
DGFX5: MOVSI T1,(1B0) ;-2^70 SPECIAL CASE
MOVE T2,T1
JRST DGFX2 ;AND GO RETURN
KLLIT: $LIT
KLEND: END