Trailing-Edge
-
PDP-10 Archives
-
AP-D543V_SB
-
klser.mac
There are 5 other files named klser.mac in the archive. Click here to see a list.
TITLE KLSER - KL10 PROCESSOR DEPENDENT CODE - FROM KISER V165 -V13204
SUBTTL J.M. FLEMMING/JMF & D.A. LEWINE/DAL/EVS 17 OCT 78
SEARCH F,S
$RELOC
$HIGH
;THIS SOFTWARE IS FURNISHED UNDER A LICENSE AND MAY ONLY BE USED
; OR COPIED IN ACCORDANCE WITH THE TERMS OF SUCH LICENSE.
;
;COPYRIGHT (C) 1973,1974,1975,1976,1977,1978 BY DIGITAL EQUIPMENT CORP., MAYNARD, MASS.
XP VKLSER,13204
; PUT VERSION NUMBER IN GLOB LISTING AND LOADER STORAGE MAP
V1088==3 ;1088 LIR VERSION NUMBER
;USER CACHE SCHEME #2
ENTRY KLSER ;LOAD KLSER IF LIBRARY SEARCH
KLSER:
REPEAT 0,<
CLK==70 ;MACRO 47 DOES NOT KNOW ABOUT CLK.
SUBTTL CLOCK1 - INTERFACE TO JOB STARTUP, STOP, AND CONTEXT SWITCHING ROUTINES
;THIS IS THE DK10 HACK FOR CLOCK INTERRUPTS
DKXINT::CONSO CLK,30 ;INTERRUPT PENDING?
JRST . ;SEE SYSINI(IOG5)
AOS TIME## ;MAKE TIME BE LATER
SKIPE CRSHWD## ;TIME FOR CRASH DUMP?
JRST SYSTOP## ;YES.
SOS HNGTIM## ;REDUCE TIME TILL SECOND
MOVEM P4,SAVEP4 ;PUT P4 IN A SAFE PLACE
MOVEI P4,.C0CDB## ;ASSUME CPU0
IFN FTMS,<
SKPCPU (0) ;SKIP IF CPU0
MOVEI P4,.C1CDB## ;NO--GET CPU1 POINTER
SOS .CPOK##(P4) ;I AM OK
SOS .CPOK##(P4) ; ..
AOS @.CPOK1##(P4) ;YOU ARE OK
>
AOS .CPUPT##(P4) ;COUNT UPTIME
SETOM .CPTMF##(P4) ;THE TIME HAS COME
SETOM .CPCKF##(P4) ;FLAG CHAN 7 INTERRUPT
CONO PI,XI.RQC## ;RING LOW PRIO CHIMES
CONO CLK,32 ;CLEAR CLOCK FLAG
MOVE P4,SAVEP4 ;RESTORE P4
JEN @CH2## ;EXIT INTERRUPT
$LOW
SAVEP4: 0
$HIGH
>
;HERE AT CLK INTERRUPT LEVEL
;THIS CODE IS DUPLICATED IN CP1SER FOR CPU1
CK0INT::SKIPN .C0CKF## ;CLK INTERRUPT REQUEST?
JRST CK0INT ;NO, CHECK OTHER DEVICES
DATAI PAG,SVPG7 ;SAVE STATUS OF PAG, MAKE SURE WE SELECT
;PROPER AC SET AT INTERRUPT EXIT
EXECAC ;SWITCH TO EXEC AC BLOCKS
CONO PI,II.CCI## ;CLEAR SOFTWARE INITIATED CLOCK INTERRUPT FLAG
MOVEM 17,.C0S17## ;SAVE AC 17
MOVE 17,CK0CHL## ;IS CURRENT JOB IN USER MODE?
TLNE 17,(XC.USR)
JRST CK0IN1 ;YES, DON'T NEED TO SAVE THE ACS
MOVE 17,.C0S17## ;IN EXEC MODE, ASSUME NOT FORCED RESCHEDULE
SKIPN .C0SCF## ;SKIP IF THE FORCED RESCHEDULING FLAG IS ON
JRST [DATAO PAG,SVPG7
JEN @CK0CHL##] ;INTERRUPTED OUT OF A UUO, LEAVE CLOCK FLAG
; SET AND DISMISS
SKIPN 17,.C0ADR## ;CURRENT JOB DATA AREA, IS THERE ONE?
MOVE 17,.C0NJD## ;NO, MUST BE KJOB OR CORE 0, RUNS AT UUO
; LEVEL AND REQUESTS A CLOCK INTERRUPT TO STOP
MOVEM 16,JOBD16##(17) ;SAVE AC 16 IN DUMP AREA OF JOB DATA AREA
MOVEI 16,JOBDAC##(17) ;SOURCE = 0, DESTINATION = DUMP AC 0
BLT 16,JOBD15##(17) ;SAVE ACS 0-15 IN DUMP AC AREA
MOVE T1,.C0S17## ;NOW SAVE 17 IN THE JOB DATA AREA
MOVEM T1,JOBD17##(17) ;ALONG WITH THE OTHER DUMP ACS
MOVE 17,CK0CHL## ;RESTORE INTERRUPT PC
CK0IN1: MOVEM 17,.C0PC## ;SAVE PC IN PROTECTED PART OF SYSTEM DATA
; STORAGE FOR CURRENT JOB
CK0SPD::MOVE P,.C0NPD## ;SETUP PUSH DOWN LIST IN NULL JOB DATA AREA
;TURN ON USER IOT SO XCTP WORKS RIGHT
CK0IN2: JRSTF @[IC.UOU+CHKAPE##] ;CHECK FOR APR ERRORS, CALL THE COMMAND
; DECODER, AND RESCHEDULE
CIP8B:: MOVE T1,.C0PC## ;GET THE PC FOR THE CURRENT JOB
TLNE T1,(XC.USR) ;IS IT IN USER MODE?
JRST [USERAC ;RESET USER AC BLOCK #'S
JEN @.C0PC##] ;DISMISS INTERRUPT
MOVSI 17,JOBDAC##(R) ;NO, RESTORE EXEC MODE ACS
BLT 17,17 ; FROM THE DUMP AC AREA
JEN @.C0PC## ;RETURN TO THE INTERRUPTED EXEC MODE PROGRAM
$LOW
SVPG7: 0 ;PLACE TO SAVE STATUS OF PAG
$HIGH
;ROUTINE TO SAVE THE USER'S ACS IN AC BLOCK 1 IN THE SHADOW AC
; AREA IN THE JOB DATA AREA ON A CONTEXT SWITCH
;CALLING SEQUENCE:
; SETUP THE USER BASE REGISTER TO POINT TO THE CURRENT JOB'S UPMP
; PUSHJ P,SAVUAC
; ALWAYS RETURN HERE
SAVUAC::PUSH P,J ;SAVE CURRENT JOB NUMBER
MOVE J,U ;J 2 JOB NUMBER OF THE LAST JOB RUN
PUSHJ P,SETUPR ;SETUP R TO POINT TO SHADOW AREA
JRST JPOPJ## ;NO CORE IN CORE
MOVEI T1,(R) ;SOURCE = USER AC 0,
; DESTINATION = AC 0 IN SHADOW AREA
EXCTUX <BLT T1,17(R)>
;SAVE USER ACS 0-17
JRST JPOPJ## ;RETURN
;ROUTINE TO RESTORE THE USER'S ACS TO AC BLOCK 1 FROM THE SHADOW AC
; AREA IN THE JOB DATA AREA ON A CONTEXT SWITCH
;CALLING SEQUENCE:
; SETUP THE USER BASE REGISTER TO POINT TO CURRENT JOB'S UPMP
; PUSHJ P,RESUAC
; ALWAYS RETURN HERE
RESUAC::PUSHJ P,SETUPR ;SETUP R TO POINT TO SHADOW AREA
POPJ P, ;NO CORE IN CORE
MOVSI T1,(R) ;SOURCE = AC 0 IN THE SHADOW AREA,
; DESTINATION = USER AC 0
EXCTXU <BLT T1,17> ;RESTORE USER ACS 0-17
POPJ P, ;RETURN
;SUBROUTINE TO SETUP R TO POINT TO SHADOW AC AREA FOR THE CURRENT JOB
;CALLING SEQUENCE:
; MOVE J,JOB NUMBER OF CURRENT JOB
; PUSHJ P,SETUPR
; RETURN HERE IF NOT THE NULL JOB BUT HAS NO CORE (CORE 0,KJOB)
; RETURN HERE - R POINTS TO THE CURRENT JOBS SHADOW ACS
SETUPR: MOVEI T1,JS.ASA ;DON'T SAVE ACS IF THE SHADOW AREA ISN'T FREE
TDNE T1,JBTSTS##(J) ;IS IT?
POPJ P, ;NO
SETRUP: SKIPN R,JBTADR##(J) ;SETUP R - DOES THE JOB HAVE CORE IN CORE?
JUMPN J,CPOPJ## ;NO, IF J IS NON-ZERO (I.E., NOT THE NULL
; JOB) GIVE NON-SKIP RETURN (JOB HAS NO ACS)
JUMPN R,CPOPJ1## ;IS IT THE NULL JOB?
MOVE R,.CPNJD##(P4) ;YES, RETURN ADDRESS OF NULL JOBS SHADOW AREA
ADDI R,JOBDAC## ; ..
JRST CPOPJ1## ;GIVE SKIP (THERE IS A PLACE TO STORE ACS) RETURN
;ROUTINE TO ENABLE/DISABLE APR FOR TRAPPING TO USER AND EXEC
;CALL: MOVEI T1, APR CONSO FLAGS FOR USER TRAPPING
; PUSHJ P,SETAPR
; RETURN WITH APR RESET AND INTERRUPT LOCATION CONSO'S SET
SETAPR::PUSH P,P4 ;SAVE P4
MOVEI P4,.C0CDB## ;SET UP CDB INDEX FOR CPU0
SETAP1::PUSHJ P,SETRP ;SETUP THE TRAP LOCATIONS (PAGE FAULT,
; ARITHMETIC, PDL OVF)
SETAP2: PUSHJ P,SETCNA ;SET USER ENABLES FOR NXM AND CLOCK AND
; SET THE APR PIA
POP P,P4 ;RESTORE P4
POPJ P, ;EXIT
;ROUTINE TO SETUP USER TRAP LOCATIONS AS SPECIFIED BY USER ENABLE BITS
; PAGE FAULT (ILL. MEM. REF.), ARITHMETIC (INTEGER OVERFLOW, FLOATING
; POINT OVERFLOW OR UNDERFLOW, AND DIVIDE CHECK), PUSH DOWN LIST OVERFLOW
; TRAP 3 IS ALWAYS IGNORED IN USER MODE.
;CALLING SEQUENCE:
; MOVE T1,USER ENABLE BITS
; PUSHJ P,SETRP
; ALWAYS RETURN HERE
;T1 IS PRESERVED.
SETRP: TRNE T1,AP.AOV+AP.FOV;IS HE?
TDZA T2,T2 ;YES, SET TO FIELD TRAPS
MOVSI T2,(JFCL) ;IGNORE ARITHMETIC TRAPS IF USER NOT ENABLED
IFN FTPI,<
HRRI T2,SAROVF ;SET DISPATCH ADDRESS
MOVEM T2,.UPMP+.UPAOT ;STORE IN UPT
>
IFE FTPI,<
HLLM T2,.UPMP+.UPAOT ;FIELD OR IGNORE USER AOF TRAPS
>
MOVEI T2,SEPDLO ;IF USER NOT ENABLED FOR POV HANDLE LIKE EXEC POV
TRNE T1,AP.POV ;IS HE ENABLED?
MOVEI T2,SUPDLO ;YES, HANDLE DIFFERENTLY
HRRM T2,.UPMP+.UPPDT ;YES, SET FOR SEPDLO OR SUPDLO TO HANDLE PDL OV
IFE FTPI,<
POPJ P, ;RETURN
>
IFN FTPI,<
PJRST APPSI## ;SETUP TRAP LOCATIONS FOR ANY INTERRUPTS THE
; USER IS ENABLED FOR
>
;SUBROUTINE TO SETUP USER'S APR CONSO MASK AND THE APR PIA
;CALLING SEQUENCE:
; MOVE T1,USER'S APR ENABLE BITS
; PUSHJ P,SETCNA
; ALWAYS RETURN HERE
SETCNA::HRL T1,T1 ;COPY ENABLE BITS TO LEFT HALF
TLZ T1,-1-XP.CLK-UE.PEF ;CLEAR ALL BITS EXCEPT CLOCK FLAG
; AND USER ENABLED MEM PARITY
TRNE T1,AP.NXM ;DOES USER WANT NXM ENABLED?
TLO T1,LP.NXM ;YES, ENABLE THAT FOR HIM
HRR T1,.CPEEB##(P4) ;SET MONITOR ENABLES
MOVEI T2,@.CPAPI##(P4) ;MOVE IN APR PIA
CONO PI,PIOFF## ;DISALLOW INTERRUPTS WHILE CHANGING APR BITS
HLRM T1,.CPCN1##(P4) ;USER'S ENABLE BITS
HRRM T1,.CPCON##(P4) ;MONITOR'S ENABLE BITS
CONO APR,(T2) ;SET PIA
CONO PI,PION## ;RESTORE PI
POPJ P, ;RETURN
;ROUTINE TO CAUSE CLK ROUTINE TO RESCHEDULE
;CALLED AT ANY LEVEL
;CALL: PUSHJ P,STOP2
; RETURN IMMEDIATELY EXCEPT IF AT UUO LEVEL
; IF AT UUO LEVEL, RETURN WHEN JOB IS RUNABLE AGAIN
STOP2:: CONO PI,PIOFF## ;PREVENT CLOCK INTERRUPT DURING STOP2 CODE
SETOM .C0CKF## ;SET FLAG TO INDICATE CLK INTERRUPT
; EVEN THOUGH CLK INTERRUPT IS NOT A TIME INTERRUPT
CONO PI,PICLK## ;TURN PI BACK ON AND REQUEST INTERRUPT TO
; CLK PI CHANNEL(LOWEST PRIORITY CHANNEL)
CONSZ PI,II.IPA ;AT INTERRUPT LEVEL?
POPJ P, ;YES, RETURN IMMEDIATELY
PUSH P,T1 ;NO, AT UUO LEVEL
STOP3: CONI PI,T1 ; MAKE SURE CLOCK LEVEL PROCESSING
TLNE T1,CLKBIT## ; HAPPENS BEFORE DOING ANYTHING ELSE
JRST STOP3 ; SINCE MAY NOT HAVE ANY CORE
JRST TPOPJ## ;RETURN
TSTREL::MOVEI T1,JS.ASA ;WHAT DOES REFERENCE TO USER 0-17 REALLY MEAN BIT
TRNN M,777760 ;IS THIS REFERENCE TO USER 0-17?
TDNN T1,JBTSTS##(J) ;YES, IS IT TO USER'S ACS OR THE SHADOW ACS?
AOS (P) ;USER'S ACS
POPJ P, ;GIVE SHADOW ACS OR USER AC SET RETURN
SAROVF::EXECAC
MOVEI P4,.C0CDB## ;ASSUME CPU0
IFN FTMS,<
SKPCPU (0) ;IS THIS CPU0?
MOVEI P4,.C1CDB## ;NO, POINT P4 AT CPU1'S CDB
>
EXCH R,.CPADR##(P4) ;GET ADDRESS OF USER'S JOB DATA AREA
MOVEM T1,.UPMP+.UPMUO ;SAVE A TEMPORARY
HLLZ T1,.UPMP+.UPMUP ;GET PC ERROR FLAGS
HRR T1,JOBENB##(R) ;GET USER'S ENABLE BITS
TLZ T1,3637 ;CLEAR NON-EXISTANT KA10 BITS FOR COMPATABLITY
TRNN T1,AP.AOV ;OVERFLOW - IS THE USER ENABLED?
TLNE T1,(XC.FOV) ;TRAP CAUSED BY FOV?
JRST SAROV2 ;YES, GO TRAP TO HIM
SAROV1: MOVE T1,.UPMP+.UPMUP ;USER IS NOT ENABLED FOR THIS EXCEPTION - RESTORE THE
JRST SAROV6 ; TRAP PC AND DISMISS TO THE INTERRUPTED PROGRAM
SAROV2: HRRI T1,AP.AOV+AP.FOV;ASSUME FLOATING OVERFLOW
TLNN T1,(XC.FOV) ;WAS IT A FLOATING OVERFLOW TRAP?
TRZ T1,AP.FOV ;NO, INTEGER OVERFLOW
HRRZM T1,JOBCNI##(R) ;SIMULATE KA10 CONI APR,JOBCNI(R)
HRR T1,.UPMP+.UPMUP ;RESTORE TRAP PC
MOVEM T1,JOBTPC##(R) ;STORE IT FOR TRAP HANDLING ROUTINE
JRST SAROV4 ;FINISH UP
SAROV3: HRRZM T1,JOBCNI##(R) ;LIKE CONI ON THE KA-10
SAROV4: HRR T1,JOBENB##(R) ;GET USER'S ENABLE BITS
TRNE T1,XP.DDU ;USER WANT TRAPS REENABLED?
JRST SAROV5 ;YES, LEAVE AS IS
HLLZS JOBENB##(R) ;CLEAR USER'S ENABLE BITS SO MUST DO APRENB AGAIN
HRRI T1,(JFCL) ;NOP
HRLM T1,.UPMP+.UPAOT ;IGNORE ARITHMETIC TRAPS
HRRI T1,SEPDLO
HRRM T1,.UPMP+.UPPDT ;EXEC WILL FIELD PDL OVERFLOWS
SETZM .CPCN1##(P4) ;CLEAR POSSIBLE NXM OR CLOCK ENABLES
SAROV5: HRR T1,.CPCN1##(P4) ;CLEAR CLOCK ENABLE SO THAT WON'T INTERRUPT HIM
TRZ T1,XP.CLK
HRRZM T1,.CPCN1##(P4) ;NEW USER ENABLE BITS
HRR T1,JOBAPR##(R) ;GET USER'S TRAP ADDRESS
SAROV6: TLZ T1,(XC.OVF+XC.FOV+XC.FUF+XC.NDV)
TLO T1,(XC.PUB) ;INSURE PUBLIC IS SET
EXCH T1,.UPMP+.UPMUO ;NEW PC WITH TRAP CAUSING BITS CLEARED
EXCH R,.CPADR##(P4) ;RESTORE R
USERAC
JEN @.UPMP+.UPMUO ;EXIT TO THE USER'S TRAP HANDLER
SEPDLO::EXECAC
MOVEM P4,.UPMP+.UPMUO ;SAVE P4
MOVEI P4,.C0CDB## ;ASSUME CPU0
IFN FTMS,<
SKPCPU (0) ;ON CPU1?
MOVEI P4,.C1CDB## ;YES, POINT P4 AT CPU1'S CDB
>
EXCH T1,.UPMP+.UPMUP ;GET THE PC
MOVEM T1,.CPAPC##(P4) ;SET AS ERROR PC FOR ERRCON
HRRI T1,AP.POV ;SET PUSH DOWN OVERFLOW FLAG
SEPDL1: TLNN T1,(XC.USR) ;WAS THE PDL OVF IN USER MODE?
JRST SEPDL2 ;NO
HRRZM T1,.JDAT+JOBCNI## ;STORE THE PDL OVF BIT
MOVE T1,.CPAPC##(P4) ;GET THE USER'S PC
MOVEM T1,.JDAT+JOBTPC## ;STORE IT FOR LATER REPORTING
MOVEI T1,JS.APE ;APR ERROR IN JOB BIT
EXCH J,.CPJOB##(P4) ;GET THE CURRENT JOB'S JOB NUMBER
IORM T1,JBTSTS##(J) ;LIGHT APR ERROR BIT
IFN FTMS,<
MOVE P,[MJOBPD##,,.JDAT+JOBPDL##] ;SETUP A PUSH DOWN LIST
PUSHJ P,CP1APE## ;MAKE SURE THE JOB IS RUNNABLE ON CPU0
; SO IT WILL GET STOPPED AND ERROR WILL BE REPORTED
>
EXCH J,.CPJOB##(P4) ;RESTORE J
JRST SEPDL3 ;AND PROCEDE
SEPDL2: HRRM T1,.CPAEF##(P4) ;IN .CPAEF SO ERRCON WILL GET CALLED
SEPDL3: MOVE T1,.UPMP+.UPMUP ;RESTORE T1
CONO PI,PIOFF ;NO INTERRUPTS UNTIL P4 IS RESTORED
SETOM .CPSCF##(P4) ;SET FORCED RESCHEDULING FLAG
SETOM .CPCKF##(P4) ;AND CLOCK FLAG
MOVE P4,.UPMP+.UPMUO ;RESTORE P4
CONO PI,PICLK## ;REQUEST A CLOCK INTERRUPT AND TURN THE PI SYSTEM ON
CONSZ PI,II.IPA ;ANY PIS IN PROGRESS?
STOPCD .,STOP,PIP, ;++PI IN PROGRESS
JRST . ;WAIT UNTIL CLOCK LEVEL HAPPENS AND THE JOB
; IS STOPPED IF IN USER MODE. IF THE PC IS IN
;EXEC MODE, ERRCON WILL CONTINUE AT
; (.CPAPC(P4)) INSTEAD OF HERE
;HERE ON A PAGE FAULT (NO UUO DONE)
SEILM:: CONO PI,PIOFF## ;NO INTERRUPTS PLEASE
EXECAC
MOVEM P4,.UPMP+.UPMUO ;SAVE P4
MOVEI P4,.C0CDB## ;ASSUME ON CPU0
IFN FTMS,<
SKPCPU (0) ;ARE WE?
MOVEI P4,.C1CDB## ;NO, POINT P4 AT CPU1'S CDB
>
MOVEM T1,.UPMP+.UPMUP ;SAVE T1 TEMPORARILY
LDB T1,[POINT 5,.UPMP+.LMPFW,5] ;PICK UP PF CODE
CAIN T1,PF.PTP ;IS IT PAGE TABLE PARITY?
JRST PTPAR ;YES,GO PROCESS
CAIE T1,PF.ARP ;IS IT AR PARITY?
CAIN T1,PF.AXP ;OR ARX PARITY?
CAIA ;YES, FALL THROUGH INTO PARTRP
JRST SEILMA ;GO HANDLE PAGE FAULT
REPEAT 0,<
AR/ARX TRAP -MEMORY PARITY HANDLING FOR KL10
BACKGROUND: BY DESIGN THE KL WILL FREEZE DATA WHICH PASSES INTO THE AR/ARX WITH BAD (EVEN) PARITY. INSTRUCTION EXECUTION IN THIS CASE
IS INTERRUPTED TO STOP PROPAGATION OF THE BAD DATA.
THE AR/ARX TRAP -MEMORY PARITY INTERRUPT HANDLING ALGORITHM
HAS THE FOLLOWING OBJECTIVES:
1. TRY, IF POSSIBLE, TO CONTINUE THE USER, IF GOOD DATA CAN BE
FOUND IN PHYSICAL MEMORY (INTERMITTENT CACHE FAILURE)
2. STOP AFFLICTED USER, WHICH IS GOING TO USE BAD DATA AND INFORM HIM
(BAD DATA ITEMS SET TO 0 TO AVOID RECURSIVE FAILURES DURING SWAPPING/PAGING)
3. STOP SYSTEM IF BAD DATA ITEM ORIGINATES OUT OF MONITOR DATA BASE.
4. LOG IN EACH INSTANCE PERTINENT INFORMATION VIA
DAEMON TO BE REPORTED LATER VIA SYSERR
5. SCAN ALL OF PHYSICAL CORE ON LINE FOR MORE BAD DATA TO GATHER
AS MUCH STATISTICAL INFORMATION FOR ANALYSIS BY FIELD SERVICE
AND HANDLE AFFECTED USERS AS IN 1 TO 4 ABOVE.
CODE IMPLEMENTATION: THE CODE IS DISPERSED IN ITS MAJORITY THRU:
KLSER - AR/ARX TRAP HANDLING AND CORE SWEEP
CLOCK1 - MEMORY PARITY HANDLING AT INTERRUPT
ERRCON - CORE SWEEP CALLS AND ERROR-MESSAGE TYPEOUT
COMMON - CPU DATA BLOCK DEFINITIONS
S - BIT DEFINITIONS FOR LOCAL FLAGS
SYSINI - "UN CACHING" OF THE FIRST PORTION OF THE MEMORY PARITY
INTERRUPT HANDLING TO SHORTEN THE "WINDOW" OF REPETITIVE CACHE
WRITE-BACK AND OTHER RECURSIVE FAILURES
"UN CACHING" OF EDDT FOR DEBUGGING (THIS IS IN REPEAT 0 FOR STD MONITOR)
TO AVOID UNNECCESSARY FURTHER SPLIT AND DUPLICATION OF CODE, THE AR/ARX TRAP
ROUTINE USES THE MEMORY PARITY INTERRUPT CODE TO KILL AFFECTED USERS, EVEN
IF NO INTERRUPT WAS PENDING, BY SIMULATING ONE. EXPECTED TRAPS/INTERRUPTS
DURING THE CORE SWEEP ARE CHECKED AGAINST THE PC OF BLT-INSTRUCTION
(MPI LABEL); A FAILURE FROM OTHER THAN THIS PC IS REGARDED AS FATAL
SINCE THE CODE IS NOT REENTRANT THE USED AC FOR THE BLT IS FIXED UP
TO ALLOW CONTINUATION OF THE BLT.
>;END REPEAT 0
;HERE ON AR OR ARX PARITY TRAP (PAGE FAIL CODE 36 OR 37)
PRTRP: EXECAC
SKIPE .CPPSP##(P4) ;CORE SWEEP IN PROGRESS?
JRST SWTRP ;YES, JUST REMEMBER LOCATION OF FAILURE AND DISMISS
CONSZ APR,LP.NXM ;IS THIS REALLY A NON-EX-MEM?
JRST PTNXM ;YES, JUST IGNORE THE TRAP
MOVEI T1,@.CPEBR##(P4) ;NORMAL EBR
TRZ T1,LG.CSW ;TURN OFF CACHE LOAD BIT
CONO PAG,@T1 ;TURN OFF CACHE LOAD AND CLEAR PAGE TABLE
MOVE T1,[EXP XC.UIO+TRYBAD] ;NEW LOCATION FOR PAGE TRAP
MOVEM T1,.UPMP+.LMPFN ;SAVE IN PAGE MAP
AOS .CPNPT##(P4) ;COUNT TOTAL NUMBER OF AR/ARX PARITY TRAPS
MOVEM 16,.CPA17##-1(P4);SAVE 16
MOVEI 16,.CPA00##(P4) ;GET BLT POINTER
BLT 16,.CPA17##-2(P4) ;SAVE AC'S IN CPU DATA BLOCK
SETZ P2, ;CLEAR THE FLAG REGISTER
MOVE T1,.UPMP+.LMPFP ;GET THE PAGE FAIL PC
MOVEM T1,.CPPPC##(P4) ;SAVE THE PC FOR ERROR REPORTING
MOVE T2,.UPMP+.LMPFW ;GET THE PAGE FAIL WORD
MOVEM T2,.CPPFW##(P4) ;SAVE THE PAGE FAIL WORD FOR DAEMON
LDB T3,[POINT 5,T2,5] ;GET PAGE FAIL CODE INTO T3
SUBI T3,PF.ARP ;CONVERT TO INDEX INTO AC BLK 7
DATAO PAG,[LG.LAB+07B11] ;SET PREVIOUS CONTEXT AC'S TO 7
PXCT PX.MEM,[MOVE T3,(T3)] ;PICK UP BAD DATA WORD
EXECAC ;SET PREVIOUS AC'S BACK
PUSH P,P1
PUSH P,P2 ;SAVE P1 &P2
MOVEM T3,.CPTBD##(P4) ;SAVE BAD DATA FOR DAEMON
RDERA .CPAER##(P4) ;SAVE THE ERA FOR ERROR REPORTING
CONI APR,.CPPEF##(P4) ;AND THE APR STATUS
PUSH P,T2 ;SAVE T2 TEMPORARILY
MOVE T1,[100000,,0] ;SBDIAG FUNCTION 0
SBDIAG T1 ;DO IT
DMOVEM T1,.CPPSB##(P4) ;SAVE THESE 2 VALUES ALSO FOR ERROR REPORTING
MOVE T1,[100000,,1] ;NOW DO SBDIAG FUNCTION 1
SBDIAG T1
DMOVEM T1,.CPPSB##+2(P4) ;SAVE THE RESULTS OF FUNCTION 1
MOVSI T1,DMACLR ;NOW CLEAR THE ERROR BITS INT THE DMA
SBDIAG T1 ;WITH FUNCTION 0
SETOM .CPTSD##(P4) ;TELL INTERRUPT WE HAVE SAVED THE DATA
MOVE T1,.CPAPI##(P4) ;GET APR PIA
TRO T1,LP.CSF!LP.SBE!LP.PAR ;CLEAR THE ERROR BITS
CONO APR,(T1) ;
POP P,T2 ;RESTORE T2
MOVE T4,[PXCT PX.MEM,[MAP P1,(T2)]] ;SET UP XCT OF MAP IN T4
MOVSI T3,(PF.USR) ;GET BIT WHICH SAYS REF WAS USER/EXEC
TDNN T3,T2 ;IF REF WAS EXEC,
TLZ T4,(PX.MEM,) ;TURN OFF PXCT BITS, SO WE JUST DO XCT OF MAP
XCT T4 ;DO A MAP TO TURN PF WORD INTO PHYS ADDR IN P1
MOVEM P1,.CPPBA##(P4) ;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
MOVE T3,.CPTOS##(P4) ;GET PAGE NUMBER OF EPMP FOR THIS CPU
MOVE T4,.MERPL(T3) ;PICK UP CONTENTS OF TEMP MAP SLOT WE WILL USE
TRO P1,PM.ACC+PM.WRT ;TURN ON ACCESS ALLOWED AND WRITE
DPB P1,[POINT 18,.MERPL(T3),17] ;PUT MAP ENTRY INTO APPROPRIATE SLOT
LSH P1,-^D27 ;TURN P1 INTO WORD NUMBER WITHIN PAGE
ADDI P1,.ERPIL ;AND GET PAGE NUMBER CORRESPONDING TO MAP SLOT
CONSO PAG,LG.CSL ;IS THE CACHE ON?
JRST PRTP1 ;NO
TRO P2,PFCPF3 ;REMEMBER ITS IN USE
SWPVA ;SWEEP CACHE-VALIDATE CORE
;BUT LEAVE CACHE VALID.
CONSZ APR,LP.CSB ;SWEEP BUSY?
JRST .-1 ;WAIT FOR DONE
CONSZ APR,LP.SBE!LP.PAR ;ERROR DURING SWEEP?
TRO P2,PFCPF4 ;REMEMBER THIS PROBLEM
MOVEI T1,@.CPEBR##(P4) ;NORMAL EBR
TRZ T1,LG.CSW!LG.CSL ;TURN OFF BOTH LOOK & LOAD
CONO PAG,@T1 ;DISABLE CACHE
MOVE T1,.CPAPI##(P4) ;GET APR PIA
TRO T1,LP.CSF!LP.SBE!LP.PAR ;CLEAR THE ERROR BITS
CONO APR,(T1) ;
MOVSI T1,DMACLR ;NOW CLEAR THE ERROR BITS INT THE DMA
SBDIAG T1 ;WITH FUNCTION 0
;HERE START RETRIES-FIRST WITH CACHE OFF
PRTP1: 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##(P4) ;SAVE THE GOOD DATA FOR ERROR REPORTING
AOS .CPSPT##(P4) ;UPDATE COUNTER OFSOFT AR/ARX PARITY ERRORS
LSH T3,^D9 ;MOVE RETRY COUNT TO BITS 18-27
HRRZ T3,T3 ;CLEAR LEFT HALF
IORM T3,.CPPTR##(P4) ;STORE RETRY COUNT
;HERE RETRY WITH CACHE ON IF IT WAS IN USE
TDNN P2,PFCPF3 ;WAS CACHE ON WHEN WE STARTED?
JRST PRTP3 ;NO
;HERE RESTORE GOOD DATA TO THE CACHE LOCATION
PUSH P,T1 ;SAVE SOME LOCATIONS FOR OUT USE
PUSH P,T2
PUSH P,T3
PUSH P,T4
PUSH P,P2
PUSH P,P3
PUSH P,P4
MOVEI P2,@.CPEBR(P4) ;GET NORMAL EBR
MOVE P3,P2 ;2 COPIES OF NORMA EBR
TRZ P3,LG.CSW!LG.CSL ;TURN OFF AFTER WRITING
MOVE P4,T1 ;SETUP GOOD DATA TO WRITE BACK TO CACHE
MOVE T1,[CONO PAG,@P2] ;TURN ON CACHE LOOK & LOAD
MOVE T2,[MOVEM P4,0(P1)] ;REWRITE GOOD DATA TO CACHE
MOVE T3,[CONO PAG,@P3] ;TURN OFF CACHE LOAD
MOVE T4,[JRST PRTP2] ;GET BACK TO THIS CODE
;EXECUTING THE ABOVE 4 INSTRUCTIONS FROM THE AC'S ENSURES THE
;FOLLOWING INSTRUCTIONS DON'T ALSO GET INTO A POSSIBLY BAD CACHE.
JRST T1 ;EXECUTE THE INSTRUCTIONS IN THE AC'S
PRTP2: POP P,P4
POP P,P3 ;RESTORE THE LOCATIONS WE JUST USED
POP P,P2
POP P,T4
POP P,T3
POP P,T2
POP P,T1
MOVEI T1,@.CPEBR##(P4) ;GET NORMAL EBR
TRZ T1,LG.CSW ;TURN OFF LOAD BIT
CONO PAG,(T1) ;TURNLOOK BACK ON
;NOW RETRY REFERENCE WITH CACHE ON, CACHE STILL HAS LOOK BIT ON BUT LOAD OFF
PUSHJ P,PRTRY ;REFERENCE LOCATION
JRST PRHCF ;RETRIES FAILED! HARD CACHE FAILURE
SWPIA ;INVALIDATE CACHE BUT DON'T TOUCH CORE
CONSZ APR,LP.CSB
JRST .-1 ;WAIT FOR "NOT BUSY"
CONO PAG,@.CPEBR##(P4) ;TURN ON CACHE LOOK & LOAD
;HERE IF RETRIES WERE SUCCESFUL, LOG SOFT ERROR AND DISMISS
PRTP3: SETZM .CPTSD##(P4) ;CLEAR THE FLAG NOW BECAUSE AN APR
;INTERRUPT MAY OCCUR WITHOUT THE TRAP
;IE, MEMORY WRITE CYCLE, AND THE INTERRUPT
;ROUTINE WOULDN'T SAVE THE DATA AND
;WOULD ALSO THINK THE ERROR WAS REALLY A USER FAILURE!!!
HRLM P2,.CPPTR##(P4) ;SAVE STATUS FLAGS IN LH OF RETRY WORD FOR ERROR REPORTING
IORM T3,.CPPTR##(P4) ;SAVE CACHE RETRY COUNT FOR ERROR REPORTING
MOVE T3,.CPTOS##(P4) ;GET .EPMP FOR THIS CPU
MOVEM T4,.MERPL(T3) ;RESTORE TEMP MAP SLOT IN THIS EPMP
MOVSI T1,(XC.USR) ;PAGE FAULT IN EXEC?
TDNE T1,.CPPPC##(P4) ;IF NOT,
MOVE P,[XWD MJOBPD##,.JDAT+JOBPDL##] ;SET UP A PDL
MOVEI T1,[ASCIZ"% RECOVERABLE AR/ARX PARITY ERROR"]
PUSHJ P,PRREP ;TELL OPR WHAT HAS HAPPENED
MOVE T1,.CPAPI##(P4) ;GET PIAS FOR THIS CPU
TRO T1,LP.CSF!LP.SBE!LP.PAR ;CLEAR APR ERRORS
CONO APR,(T1)
MOVSI T1,DMACLR ;NOW CLEAR THE ERROR BITS INT THE DMA
SBDIAG T1 ;WITH FUNCTION 0
CONO PI,PION## ;RESTORE PI SYSTEM
MOVEI T1,.ERKDT ;CODE FOR DAEMON
HRL T1,P4 ;THIS CPU'S CDB ADDRESS
PUSHJ P,DAEEIM## ;PUT THE ENTRY IN THE QUEUE
PUSHJ P,CALSW ;SET UP AND CALL SWEEPER AT PI7 LEVEL
POP P,P2
POP P,P1 ;RESTORE P1&P2 JUST IN CASE
MOVSI 16,.CPA00##(P4) ;BLT PNTR TO RESTORE AC'S
BLT 16,15 ;RESTORE AC'S
MOVE 16,.CPA17##-1(P4) ;AC 16 ALSO
;NOTE THAT MOVSI T1, BLT T1, SHOULD
;NOT BE USED EVEN THOUGH PI IS OFF
;BECAUSE OF PI0.
JRST PTPR2 ;AND RETURN
;ROUTINE TO SET UP AND REQUEST A CORE SWEEP AT PI7 LEVEL
;CALL; PUSHJ P,CALSW
;RETURNS +1 ALWAYS
CALSW: EXCH J,.CPJOB##(P4) ;GET CURRENT JOB FOR SWEEP
EXCH R,.CPADR##(P4) ;GET R SETUP
HLLZ T1,.CPMPS##(P4) ;GET SWEEP REQUEST BITS
TRO T1,UE.PEF ;SAY A PRITY ERROR OCCURED
IORM T1,.CPAEF##(P4) ;SET FLAGS FOR PI 7 SWEEP
MOVEM T1,.JBCNI##(R) ;STORE ERROR FLAGS
MOVE T1,.CPPPC##(P4) ;GET STORED PC
MOVEM T1,.CPMPP##(P4) ;STORE FOR PI7
MOVEM T1,.CPLPP##(P4) ;STORE FOR "LAST PC"
MOVEM T1,.CPAPC##(P4) ;STORE FOR SWEEP ERROR REPORTING
MOVEM T1,JOBTPC##(R) ;STORE FOR USER
IFN FTMS,<
PUSHJ P,CP1APE## ;MAKE SURE JOB WILL RUN ONCPU0
;SO ERROR MSG WILL PRINT
>;END IFN FTMS
EXCH R,.CPADR##(P4) ;RESTORE R
EXCH J,.CPJOB##(P4) ;RESTORE J
SETOM .CPPSP##(P4) ;SET SWEEPING FLAG NOW TO CLOSE DOWN
;WINDOW WHICH ALLOWS RECURSIVE LOOPING
SETOM .CPSCF##(P4) ;FORCE NOSCHED
MOVE T1,[EXP XC.UIO+SEILM] ;GET ORIGINAL PAGE FAIL TRAP ADDR
MOVEM T1,.UPMP+.LMPFN ;AND RESTORE IT IN UPMP
SETOM .CPCKF##(P4) ;SET FLAG FOR PI7 INTERRUPT
MOVEI T1,PARDLY ;SET A STALL COUNTER
CONO PI,XI.RQC## ;CALL SWEEPER
SOJGE T1,. ;WAIT FOR THE INTERRUPT
POPJ P,0 ;RETURN TO CALLER
;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
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?
PJRST CPOPJ1 ;NO-GIVE GOOD RETURN
CAIGE T3,TRPTRY ;RETRY COUNT EXHAUSTED?
AOJA T3,PRTY1 ;NO-TRY AGAIN
POPJ P,0 ;YES-GIVE ERROR RETURN
;HERE ON TRAPS OCCURING DURING REVOVERY ATTEMPTS
TRYBAD: TRNN P2,PFCPF0 ;BECAUSE OF TEST REFERENCE?
STOPCD (.,HALT,UPF) ;++UNEXPECTED PAGE FAIL
LDB T1,[POINT 5,.UPMP+.LMPFW,5] ;GET PAGE FAIL CODE
CAIE T1,PF.ARP ;AR PARITY ERROR?
STOPCD (.,HALT,WPT) ;++WRONG PARITY TRAP
TRO P2,PFCPF2 ;YES-INDICADE ERROR
AOS .UPMP+.LMPFP ;RETURN TO TEST REFERENCE + 1
JRSTF @.UPMP+.LMPFP ;GO BACK FOR ANOTHER TRY
;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
CONSZ APR,LP.CSB
JRST .-1 ;WAIT FOR "NOT BUSY"
MOVEI T1,@.CPEBR##(P4) ;INITIAL EBR
TRZ T1,LG.CSL ;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##(P4) ;COUNT THIS FAILURE
CAIGE T1,CCHEMX ;EXCEEDED ALLOWABLE?
JRST PRHC1 ;NO-TURN IT BACK ON
HRRZ U,CTYLDB## ;TEL HIM WHERE TO PUT MESSAGE
PUSHJ P,INLMES
ASCIZ"
% 3 hard failures in cache - cache will be deselected"
MOVE T1,.CPEBR##(P4) ;GET NORMAL EBR
TRZ T1,LG.CSL!LG.CSW ;TURN OFF LOOK & LOAD BITS
MOVEM T1,.CPEBR##(P4) ;BITS NOW CLEARED SO OTHERS
;CAN'T TURN IT ON BY ACCIDENT
;FIRST MESSAGE IS SENT TO OPR TO TELL HIM WE ARE ATTEMPTING TO TURN
;IT OFF, THE STOPCD WILL INDICATE IT IS OFF
STOPCD (.+1,DEBUG,CTO) ;++CACHE TURNED OFF
;STOPCD IS ALSO USED SO THAT ERROR
;REPORTING GETS THE MESSAGE
JRST PRTP3 ;NOW CLEAN UP AND RETURN TO USER
;HERE TO TURN THE CACHE BACK ON
PRHC1: CONO PAG,@.CPEBR##(P4) ;TURN IT ON
JRST PRTP3 ;AND RETURN TO USER
;HERE WHEN RETRIES FROM MEMORY FAIL-COULD BE EITHER FROM MEMORY OR CACHE
;HOWEVER WE MUST NOW CRASH THE USER
; IF PFCPF4 IS SET, FAILURE
;ORIGINATED IN CACHE
PRHMF: SETZM .CPTGD##(P4) ;CLEAR THE GOOD DATE FOR ERROR REPORTING SINCE WE NEVER GOT ANY
MOVEI T1,[ASCIZ "%NON-RECOVERABLE AR/ARX PARITY ERROR"]
PUSHJ P,PRREP ;CALL AR/ARX TYPEOUT ROUTINE
AOS .CPHPT##(P4) ;HARD (AR/ARX) PARITY TRAP COUNT
MOVSI T1,(XC.USR) ;TEST IF WE WERE IN USER MODE
TDNN T1,.CPPPC##(P4) ;AT THE TIME OF THE TRAP
STOPCD .,HALT,PTH, ;PARITY TRAP HALT
SWPIA ;INVALIDATE CACHE BUT DON'T TOUCH CORE
CONSZ APR,LP.CSB ;WAIT FOR
JRST .-1 ;BUSY TO GO AWAY
MOVE T1,.CPAPI##(P4) ;GET APR PIA
TRO T1,LP.CSF!LP.SBE!LP.PAR ;CLEAR ERROR BITS
CONO APR,(T1) ;DO THE REAL CLEARING
MOVSI T1,DMACLR ;NOW CLEAR THE ERROR BITS INT THE DMA
SBDIAG T1 ;WITH FUNCTION 0
;MONITOR IS OK, CRASH USER
TRO P2,PFCPF1 ;SAY HARD ERROR FOR ERROR REPORTING
HRLM P2,.CPPTR##(P4) ;SAVE FLAGS
LSH T3,^D9 ;MOVE RETRY COUNT TO BITS 18-26
HRRZ T3,T3 ;CLEAR LEFT HALF
IORM T3,.CPPTR##(P4) ;SAVE RETRY COUNT FOR ERROR REPORTING
MOVE T1,[EXP XC.UIO+SEILM] ;GET ORIGINAL PAGE FAIL TRAP ADDR
MOVEM T1,.UPMP+.LMPFN ;AND RESTORE IT IN UPMP
MOVEI T1,.ERKDT ;SETUP ERROR CODE
HRL T1,P4 ;AND CDB ADDRESS
PUSHJ P,DAEEIM## ;CALL DAEMON TO LOG ERROR
CONO PI,PIOFF## ;SINCE HE LEFT IT ON
MOVE T1,.CPAPI##(P4) ;GET APR PIA
TRO T1,LP.SSF!LP.SBE!LP.PAR ;SET THE ERROR BITS
CONO APR,(T1) ;
MOVSI T1,DMACLR ;NOW CLEAR THE ERROR BITS INT THE DMA
SBDIAG T1 ;WITH FUNCTION 0
POP P,P2
POP P,P1 ;RESTORE P1&P2
CONO PAG,@.CPEBR##(P4) ;TURN CACHE BACK ON
MOVEI T1,PARDLY ;SET STALL TIME
CONO PI,PION## ;RESTORE PI SYSTEM
SOJG T1,. ;AND WAIT FOR THE INTERRUPT TO SWEEP CORE AND KILL USER
MOVE J,.CPJOB(P4) ;GET THE OFFENDING JOB #
JRST ESTOP## ;AND STOP HIM, WITHOUT COMING BACK HERE.
;HERE ON TRAP DURING PARITY SWEEP - JUST FLAG THAT IT HAPPENED
SWTRP: HRRZ T1,.UPMP+.LMPFP ;GET PC OF TRAP
CAIE T1,MPI ;IF THIS IS DURING PARITY SWEEP, WE
; HAD BETTER HAVE GOTTEN THE TRAP FROM
; THE MPI INSTRUCTION
STOPCD (.,HALT,NPI) ;++NOT PARITY INSTRUCTION
;NOW SAVE BAD DATA AND SET NEW PAGE FAIL TRAP ADDRESS
MOVE T1,.UPMP+.LMPFP ;GET FLAGS & PC TO RETURN TO
PUSH P,P2 ;SAVE P1&P2 FOR SWEEPER
PUSH P,T1 ;SAVE THE PC WE MUST RETURN TO!!!
PUSH P,T2 ;SAVE THE TEMP AC'S TO BE SAFE
PUSH P,T3
PUSH P,T4
MOVE T2,.UPMP+.LMPFW ;GET PAGE FAIL CODE
LDB T3,[POINT 5,T2,5] ;INTO T3
SUBI T3,PF.ARP ;CONVERT TO INDEX
DATAO PAG,[LG.LAB+07B11] ;SET PREVIOUS AC BLOCK TO 7
PXCT PX.MEM,[MOVE T3,(T3)] ;GET BAD DATA WORD FOR DAEMON
EXECAC ;GO BACK TO OUR OWN AC'S
MOVEM T3,.CPTBD##(P4) ;SAVE FOR SWEEP ROUTINE
MOVE T1,[EXP XC.UIO+TRYBAD] ;NEW LOCATION FOR TRAP ADDRESS
MOVEM T1,.UPMP+.LMPFN ;SAVE IN PAGE MAP
PUSH P,P1
;HERE DO RETRIES TO CORE, P1 ALREADY HOLDS ADDRESS TO REFERENCE
;FROM THE SWEEP INST
SWTP1: PUSHJ P,PRTRY ;TRY AGAIN 3 TIMES
JRST SWTP2 ;HARD FAILURE
;RETRIES WORKED, NOW CLEAR APR AND FAKE A SUCCESSFUL SWEEP INSTR.
POP P,P1 ;GET P1 BACK FOR A LITTLE WHILE
AOS P1 ;BUMP RIGHT HALF
HRL P1,P1 ;AND LEFT HALF TO CORRECT THE BLT POINTER
PUSH P,P1 ;THAT LITTLE WHILE FOR P1 HAS JUST EXPIRED!!
SOS .UPMP+.LMPFP ;-1 NOW SO AOS LATER HOLDS PC AT CURRENT MPI
;AND THE BLT GETS "CONTINUED"
MOVE T1,.CPAPI##(P4) ;GET PIAS FOR THIS CPU
TRO T1,LP.CSF!LP.SBE!LP.PAR ;CLEAR APR ERRORS
CONO APR,(T1)
SKIPA ;DON'T INDICATE AN ERROR TO SWEEPER
SWTP2: SETOM .CPPTH##(P4) ;INDICATE ERROR ON SWEEP INST
POP P,P1 ;
POP P,T4 ;RETURN THE TEMP AC'S
POP P,T3
POP P,T2
POP P,T1 ;GET BACK THE PC TO RETURN TO
POP P,P2
MOVEM T1,.UPMP+.LMPFP ;AND STORE IT
MOVE T1,[EXP XC.UIO+SEILM] ;RESTORE ORIGINAL TRAP ADDRESS
MOVEM T1,.UPMP+.LMPFN ;INTO PAGE MAP
AOS .UPMP+.LMPFP ;IT'S OK, INCREMENT PC SO WE DON'T TRAP FOREVER
;.CPPTH WILL TELL THE SWEEP SOMETHING
; WENT WRONG
JRST PTPR1 ;DISMISS BACK TO SWEEP ROUTINE
;ROUTINE TO PRINT A MESSAGE FOLLOWED BY "AT EXEC(USER) PC XXXXXX"
; MESSAGE FOLLOWS CALL TO THE ROUTINE, AS IN INLMES
PRREP: PUSHJ P,SAVE1## ;SAVE P1 TO REMEMBER ADDRESS OF MESSAGE
MOVE P1,T1 ;SAVE
PUSHJ P,SVPPC## ;SWITCH TO SECONDARY PROTOCOL
PUSH P,COMTOA## ;SAVE COMMAND OUTPUT ADDRESS
MOVEI T2,CTYWAT## ;GET ONE THAT DOESN'T USE PI SYS
MOVEM T2,COMTOA##
HRRZ U,CTYLDB## ;GET CTY LDB IN U
PUSHJ P,CRLF## ;START WITH CRLF
MOVE T1,P1 ;GET ADDRESS OF MESSAGE IN T1
PUSHJ P,CONMES## ;PRINT MESSAGE
MOVE T2,.CPPPC##(P4) ;GET SAVED PC
PUSHJ P,PCP## ;PRINT "AT EXEC/USER XXXXXX"
PUSHJ P,CRLF## ;END WITH A CRLF
POP P,COMTOA## ;RESTORE SCNSER ADDRESS
POPJ P, ;RETURN
;HERE ON PAGE TABLE PARITY TRAP (PF CODE 25)
PTPAR: CONO PI,PION## ;RESTORE PI SYSTEM
CONO PAG,@.CPEBR##(P4) ;CLEAR THE PAGE TABLE
AOS .CPPTP##(P4) ;COUNT A PAGE TABLE PARITY ERROR
SKIPGE T1,.CPPTF##(P4) ;PICK UP COUNT OF PAGE TABLE FAILURES
MOVEI T1,^D10 ;NONE YET, INITIALIZE
SOSG T1 ;COUNT DOWN
;IF COUNT HASN'T EXPIRED,JUST RETRY
; COUNTER IS RESET ON EVERY APR CLOCK
; TICK- IF TOO MANY FAILURES IN
; ONE TICK, WE HALT HERE
STOPCD .,HALT,PTP, ;PAGE TABLE PARITY
MOVEM T1,.CPPTF##(P4) ;REMEMBER COUNTER
MOVE T1,.UPMP+.LMPFP ;GET PAGE FAIL PC
MOVEM T1,.CPPPC##(P4) ;SAVE FOR PRINT ROUTINE
MOVEI T1,[ASCIZ "%PAGE TABLE PARITY ERROR"]
PUSHJ P,PRREP ;PRINT THE MESSAGE OUT
PTPR1: MOVE T1,.UPMP+.LMPFP ;GET PC
JRST PTRET ;RETURN TO TRAPPER
PTPR2: MOVE T1,.CPPPC##(P4) ;GET ORIGINAL PAGE FAIL OLD PC
MOVEM T1,.UPMP+.LMPFP ;WHICH IS CORRECT ADDRESS TO DISMISS TO
PTRET: MOVE P4,.UPMP+.UPMUO ;RESTORE P4
TLNN T1,(XC.USR) ;WERE WE IN EXEC MODE?
SKIPA T1,.UPMP+.UPMUP ;RESTORE T1
USERAC ;NO, RESTORE US BACK TO USERS AC'S
; CLOCK LEVEL WILL LOG SOFT ERROR
JRSTF @.UPMP+.LMPFP ;RESTORE FLAGS AND RETURN
; IF WE EVER GET THERE
;HERE ON PRITY ERROR CAUSED BY NXM
PTNXM: CONO PI,PION## ;RESTORE PI SYSTEM
JRST PTPR1 ;AND IGNORE THE TRAP
SEILMA: CONO PI,PION## ;RESTORE THE PI SYSTEM
MOVE T1,.UPMP+.UPMUP ;GET T1 BACK
EXCH T1,.UPMP+.LMPFP ;SAVE T1 AND GET THE PC
MOVEM T1,.CPAPC##(P4) ;STORE IT AS POTENTIAL ERROR PC
MOVEM T1,.UPMP+.UPMUP ;STORE WHERE KI WOULD PUT IT
EXCH T2,.UPMP+.LMPFW ;GET THE USER PAGE FAIL WORD
MOVEM T2,.CPPFW##(P4) ;SAVE PAGE FAULT WORD FOR CRASH
DPB T2,[POINT 18,T2,32] ;SHIFT VIRTUAL ADDRESS OVER 3 PLACES
ROT T2,6 ;PLACE PAGE FAIL CODE AND VIRTUAL ADDRESS
;WHERE IT WAS ON KI10
TRZE T2,40 ;USER BIT ON?
TLO T2,(1B8) ;YES, SET IT WHERE KI10 USER BIT WAS
;WE NOW HAVE KI10 STYLE PAGE FAIL WORD.
AND T2,[1777,,37] ;CLEAR UNUSED BITS
TLNE T2,(1B8) ;USER REF?
TRNN T2,10 ;YES, ACCESS ALLOWED OFF?
JRST SEILMB ;NOT USER REF OR ACCESS ALLOWED OFF
TRNN T2,4 ;USER REF, ACCESS ALLOWED ON. WRITE OFF?
TRO T2,1 ;YES, DEDUCE THAT HE TRIED TO WRITE
SEILMB: TLNE T1,(XC.USR) ;PAGE FAULT IN EXEC MODE?
JRST SEILM0 ;NO, PROCEED
ANDI T2,37 ;CLEAR ALL BUT THE PAGE FAIL CODE
CAIE T2,PF.ABF ;WAS THE PAGE FAULT AN ADDRESS BREAK?
STOPCD .+1,JOB,IME, ;++ILL MEM REF FROM EXEC
JRST SEILM1 ;YES, REMEMBER IT AND GO AWAY
SEILM0: EXECAC
MOVE P,[XWD MJOBPD##,.JDAT+JOBPDL##] ;SETUP A PUSH DOWN LIST
MOVE T3,T2 ;FAULT WAS IN USER MODE, SAVE PFC FOR
; POSSIBLE CALL TO USRFLT
ANDI T2,37 ;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
IFN FTVM,<
MOVE T4,T1 ;PC WORD INTO T4 FOR USRFLT
>
HRRI T1,AP.ILM ;ILLEGAL MEMORY REFERENCE
CAIN T2,PF.PRV ;WAS IT A PROPRIETARY VIOLATION?
IFE FTVM,<
TRO T1,AP.PPV ;YES, INDICATE THAT
>
IFN FTVM,<
TROA T1,AP.PPV ;INDICATE PROPRIETARY VIOLATION (AVOID CALL TO USRFLT)
PUSHJ P,USRFLT## ;SEE IF PAGE FAULT FOR A VM USER
; WILL NOT RETURN IF SO (DISPATCH TO USER)
MOVEM T4,.CPAPC##(P4) ;STORE ERROR PC
>
MOVE T2,.UPMP+.LMPFW ;RESTORE T2
JRST SEPDL1 ;GO SAY "ILL. MEM. REF."
SEILM1: TLO T1,(IC.AFI) ;INHIBIT ADDRESS BREAK WHEN INSTRUCTION IS
; EXECUTED AGAIN
EXCH J,.CPJOB##(P4) ;GET JOB
PUSH P,W ;SAVE W IN CASE IN EXEC MODE
PUSHJ P,FNDPDS## ;FIND THE PDB
LDB T2,[POINT 9,.PDABS##(W),17] ;GET THE PROCEED COUNT
SOSL T2 ;DECREMENT
DPB T2,[POINT 9,.PDABS##(W),17] ;STORE IT BACK IF POSITIVE
POP P,W ;RESTORE W
JUMPG T2,SEILM3 ;DON'T BREAK IF PROCEED COUNT .GT. 0
MOVE T2,JBTSTS##(J) ;IS THIS A JACCT
TLNE T2,JACCT ;JOB
JRST SEILM3 ;YES-IGNORE BREAK
EXCH J,.CPJOB##(P4) ;UNDO LAST EXCH
TLNN T1,(XC.USR) ;PC IN USER MODE?
JRST SEILM2 ;NO, REMEMBER BREAK AND GO AWAY
MOVE R,.CPADR##(P4) ;SETUP R
MOVEM T1,.CPAPC##(P4) ;STORE THE PC WITH IFA ON
IFN FTPI,<
MOVE J,.CPJOB##(P4) ;JOB NUMBER FOR PSISER
SIGNAL C$ADRB ;SIGNAL THAT AN ADDRESS BREAK HAS OCCURED
JRST [MOVE T1,.CPAPC##(P4) ;PC TO T1
JRST SEILM5] ;INTERRUPT TO THE USER
> ;END FTPI
PUSH P,.CPAPC##(P4) ;SAVE PC ON STACK
IFN FTMS,<
PUSHJ P,ONCPU0## ;MUST BE ON CPU0 TO REPORT THE BREAK
>
PUSHJ P,TTYFUW## ;FIND THE USER'S TTY
PUSHJ P,INLMES## ;REPORT THE ADDRESS BREAK
ASCIZ /
%Address break at user PC /
HRRZ T1,(P) ;GET THE USER'S PC
PUSHJ P,OCTPNT## ;TELL HIM WHERE THE BREAK OCCURED
IFN FTPI,<
PUSHJ P,PSIERR## ;PENDING INTERRUPT?
JFCL
PJRST ERRGOU## ;YES, GIVE IT OT THE USER
>
PJRST HOLDW## ;STOP THE JOB IN A CONTINUABLE STATE
SEILM2: MOVEI T2,JS.ASA ;AC'S ARE IN THE SHADOW AREA BIT
EXCH J,.CPJOB##(P4) ;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##(P4) ;RESTORE J
SEILM4: TLNE T1,(XC.USR) ;BREAK OUT OF USER MODE?
JRST SEILM5 ;YES
EXCH T1,.UPMP+.LMPFP ; AND T1
MOVE T2,.UPMP+.LMPFW ; AND T2
MOVE P4,.UPMP+.UPMUO ; AND P4
JRSTF @.UPMP+.LMPFP ;GO AWAY AND TELL THE USER ABOUT THE BREAK
; AT UUO EXIT
SEILM5: MOVEM T1,.UPMP+.LMPFP ;SAVE PC
USERAC ;USER'S AC BLOCK
JRSTF @.UPMP+.LMPFP
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,<
PUSHJ P,CPUCDB## ;SETUP P4 TO POINT TO THE CURRENT CPU'S CDB
MOVE T2,JOBPD1##(R) ;GET UUO PC
MOVEM T2,.CPAPC##(P4) ;STORE IT WHERE PSISER EXPECTS IT
SIGNAL C$ADRB ;SIGNAL THAT AN ADDRESS BREAK OCCURED
POPJ P, ;USER IS ENABLED, UUO EXIT WILL INTERRUPT TO HIM
>
IFN FTMS,<
PUSHJ P,ONCPU0## ;MUST BE ON CPU0 TO WRITE A MESSAGE
>
PUSHJ P,TTYFUW## ;FIND THE USER'S TTY
PUSHJ P,INLMES## ;REPORT THE ADDRESS BREAK
ASCIZ /
%Address break at exec PC /
HRRZ T1,.UPMP+.UPMUP ;GET THE PC WHERE THE LAST BREAK OCCURED
PUSHJ P,OCTPNT## ;TELL HIM THAT
MOVEI T1,[ASCIZ/; UUO/]
PUSHJ P,CONMES##
MOVE T2,JOBPD1##(R) ;GET THE UUO PC
PUSHJ P,PCP## ;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
PJRST HOLDW## ;AND STOP THE JOB IN A CONTINUABLE STATE
;HERE FROM SEILM IF PAGE FAULT IS IN USER MODE AND APRENB DONE
; T1=USER PC AND T3=PAGE FAULT WORD
SUILM: MOVE R,.CPADR##(P4) ;GET THE ADDRESS OF THE USER'S JOB DATA AREA
IFN FTVM,<
MOVE T4,T1 ;MOVE THE PC TO T4 FOR USRFLT
PUSHJ P,USRFLT## ;SEE IF PAGE FAULT FOR VM USER
; WILL NOT RETURN IF SO (DISPATCH TO PFH)
>
TLZ T1,3637 ;CLEAR NON-EXISTANT KA-10 BITS FOR COMPATABILITY
MOVEM T1,JOBTPC##(R) ;SAVE ERROR PC FOR USER
HRRI T1,AP.ILM ;SET ILM BIT FOR USER
JRST SAROV3 ;FINISH UP
SUPDLO: EXECAC
MOVEI P4,.C0CDB## ;ASSUME ON CPU0
IFN FTMS,<
SKPCPU (0) ;ARE WE?
MOVEI P4,.C1CDB## ;NO, ON CPU1
>
EXCH R,.CPADR##(P4) ;GET ADDRESS OF USER'S JOB DATA AREA
MOVEM T1,.UPMP+.UPMUO ;SAVE A TEMPORARY
MOVE T1,.UPMP+.UPMUP ;GET ERROR PC
TLZ T1,3637
MOVEM T1,JOBTPC##(R) ;SAVE FOR USER TO LOOK AT
HRRI T1,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,.C0JOB## ;J=CURRENT JOB NUMBER
MOVEI T1,0
DPB T1,JBYHSS## ;FORCE MAP TO BE REDONE
SETREL::PUSH P,P4 ;SAVE P4
MOVEI P4,.C0CDB## ;SETUP P4 TO POINT TO CPU0 CDB
SKIPA J,.C0JOB## ;J = CURRENT JOB NUMBER
SETRL1::PUSH P,P4 ;SAVE P4
MOVE R,JBTADR##(J) ;R = XWD PROTECTION,,EXEC VIRTUAL ADDRESS
; OF THE FIRST PAGE OF THE LOW SEGMENT
MOVEM R,.CPADR##(P4) ;SET .CPADR FOR QUICK ACCESS AT APR LEVEL
HLRZM R,.CPREL##(P4) ;SET .CPREL FOR ADDRESS CHECKING
IFN FTTRPSET,<
SKIPE .CPSTS##(P4) ;HAS TIME-SHARING BEEN STOPPED BY A TRPSET UUO?
JRST 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
PUSHJ P,STEUB ;NO, SET THE USER BASE REGISTER
jumpe r,setrlz ;done if null job
LDB T1,JBYLSS## ;GET THE PREVIOUS SIZE OF THE LOW SEGMENT
LDB T2,[POINT 9,R,8];GET THE CURRENT SIZE
CAIE T1,(T2) ;IS IT THE SAME SIZE AS IT WAS THE LAST
; TIME THIS JOB WAS RUN?
PUSHJ P,MAPLOW ;NO, REDO THE MAP
IFE FTVM,<
HLRZM R,JOBREL##(R) ;SET THE SIZE OF THE LOW SEGMENT FOR THE USER
>
IFN FTVM,<
SKIPN T1,.UPMP+.UPREL ;HOLEY PROGRAM?
HLR T1,R
HRRZM T1,JOBREL##(R) ;STORE HIGHEST CORE-UUO ADDRESS IN JOBREL
>
IFN FT2REL,<
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 ;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 ;INDICATE MAP HAS BEEN REDONE NOW
ANDCAM T1,JBTSGN##(J)
>
SETRLZ:
IFN FTSET,<
PUSHJ P,FDNJP ;FIND THE NULL JOB'S PDB
MOVE T3,T1 ;SAVE THE ADDRESS OF THE NULL JOB'S PDB
PUSHJ P,FNDPDS ;FIND THE CURRENT JOB'S PDB
>
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) ;SET THE LOAD BIT
IFN FTRTTRP,<
MOVEM T1,.CPDTO##(P4) ;SAVE FOR RTTRP INTERRUPT LEVEL USE
>
IFN FTSET,<
.SKIPE T2,.PDABS##(W) ;DOES THE USER HAVE ADDRESS BREAK SETTINGS?
TLNN T2,(OC.ABE) ;YES, IS HE ENABLED FOR BREAKS
MOVE T2,[EXP OC.FEP+CURJOB##] ;NO, DISPLAY JOB NUMBERS
>
DATAO PAG,T1 ;SETUP THE UBR
IFN FTSET,<
TLZ T2,777(OC.BSU) ;CLEAR PROCEED COUNTER AND 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) ; ..
.SKIPL .PDABS(T3) ;CAN USERS USE ADDRESS BREAK?
DATAO APR,T2 ;YES, SETUP BREAK CONDITIONS AND BREAK ADDRESS
MOVEM T2,.CPAPR##(P4) ;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,JOBENB##(R) ;JOB'S APR ENABLE BITS
JRST SETAP2 ;SETUP APR ENABLE BITS FOR THE USER
; NO ENABLES IF NULL JOB OR NO CORE IN CORE
;ROUTINE CALLED BY SWAPPER TO ENSURE IT HAS A PAGE MAP SET UP
GETUBR::MOVE J,.CPJOB##(P4) ;CURRENT JOB
HRRZ J,JBTUPM##(J) ;GET PAGE MAP PAGE
JUMPN J,CPOPJ## ;IF ALREADY SET UP
;; PJRST STEUB ;ELSE SET UP NULL JOB'S MAP
;ROUTINE TO SETUP USER AND EXEC BASE REGISTERS FOR A JOB
;CALLING SEQUENCE:
; MOVE J,JOB NUMBER
; PUSHJ P,STEUB
STEUB:: CAILE J,JOBMAX## ;IS THIS A LOW SEGMENT?
POPJ P, ;NO, 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
TRNN T1,17777 ;IS THERE A UPMP
JRST TPOPJ## ;NO, DON'T CLOBBER UBR
TLO T1,(LG.LUB) ;REQUEST LOADING OF UBR
DATAO PAG,T1 ;SET FOR CURRENT USER AND CLEAR THE AM
JRST TPOPJ## ;RESTORE T1 AND RETURN
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
; CALL WITH C(P4) = CPU DATA BLOCK. ACCMON AND ACCMOF PRESERVE ALL AC'S
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,PIOFF## ;TURN OFF PI'S SO ACCOUNTING METER AND PERF METER
; WILL STAY IN SYNC
CONO MTR,(T1) ;SET STUFF, TURN METER ON
SKIPE .CPAPS##(P4) ;IF ACCT/PERF METER SYNC,
PUSHJ P,SCDPMR ;GO TURN PERFORMANCE METER ON IF NECESSARY
CONO PI,PION## ;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,PIOFF## ;TURN OFF PI'S
CONO MTR,(T1) ;STOP THE CLOCK
SKIPE .CPAPS##(P4) ;ACCOUNTING/PERF SYNC?
PUSHJ P,STPPMR ;YES, TURN OFF PERFORMANCE METER
CONO PI,PION## ;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
CLREBT::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
POPJ P, ;RETURN
CLRMBT::DATAI PAG,1(P) ;SEE ABOVE
DATAO PAG,1(P)
SETZM .UPMP+.LMMBL ;LOW ORDER FIRST
SETZM .UPMP+.LMMBH ;THEN HIGH
POPJ P, ;RETURN
>;END IFN FTEMRT
SUBTTL COMCON - INTERFACE TO COMMAND DECODER MODULE
;ROUTINE TO SETUP THE USER BASE REGISTER FOR COMMAND PROCESSING
;CALLING SEQUENCE:
; PUSHJ P,COMUBR
; ... ALWAYS RETURN HERE - UBR POINTS TO THE UPMP OF THE
; JOB THAT TYPED A COMMAND
COMUBR::MOVE T1,.C0JOB## ;T1=JOB NUMBER OF CURRENTLY RUNNING JOB
HRRZ T1,JBTUPM##(T1) ;JOB HAVE A UPMP? (NO, ONLY IF THE CURRENT
; JOB DID LOGOUT UUO GIVING BACK ALL
; OF ITS CORE)?
JUMPE T1,STEUB ;NO, DON'T SAVE THE UBR SINCE IT POINTS
; A UPMP WHICH HAS BEEN RETURNED
; TO THE FREE CORE LIST - JUST POINT THE
; UBR AT THE UPMP OF THE JOB THAT THE
; COMMAND IS BEING DONE FOR
JRST SVEUB ;SAVE AND SETUP THE UBR
;HERE IF THE USER TYPED SET BREAK
IFN FTSET,<
SETBRK::PUSHJ P,SAVE2## ;SAVE P1,P2
PUSHJ P,FNDPDS## ;FIND THE PDB FOR THIS USER
PUSHJ P,CTEXT## ;GET THE FIRST ARGUMENT
JUMPE T2,NOTENF## ;IF NONE, COMPLAIN
PUSHJ P,GETNUM ;SEE IF ARGUMENT TYPED IS A NUMBER
JRST SETBR2 ;NOT A NUMBER, LOOK FOR LEGAL TEXT
SETBR1: CAIN P1,-1 ;DON'T ALLOW -1 FOR THE TIME BEING SINCE IT
; CONFUSES THE HARDWARE
JRST COMERA## ;COMPLAIN
.HRRM P1,.PDABS##(W) ;STORE THE BREAK ADDRESS
PUSHJ P,CTEXT## ;GET THE NEXT ARGUMENT
JUMPN T2,SETBR2 ;JUMP IF ONE WAS TYPED
SKIPN P2,P1 ;BREAK ADDRESS ZERO?
JRST SETB10 ;YES, TREAT SET BREAK 0 WITH NO CONDITION LIKE NONE
.HLLZ P2,.PDABS##(W) ;GET PREVIOUS CONDITIONS IF ANY
SETB1A: TLNN P2,(OC.BCI+OC.BCD+OC.BCW+OC.BCM) ;WERE THERE ANY PREVIOUSLY?
TLO P2,(OC.BCI+OC.BCD+OC.BCW) ;NO, ASSUME ALL
JRST SETBR8 ;ENABLE BREAK, STORE CONDITIONS, AND GO AWAY
SETBR2: MOVE T1,[-4,,BRKLS1] ;TABLE LENGTH,,ADDRESS OF THE TABLE
PUSHJ P,FNDNAM## ;RECOGNIZABLE TEXT ARGUMENT?
JRST SETBR5 ;NO, POSSIBLY IN ANOTHER CONTEXT
MOVE P2,T1 ;INDEX INTO BRKTBL
JUMPN T1,SETBR3 ;JUMP IF THE USER DIDN'T TYPE 'NONE'
;HERE WHEN THE USER TYPED 'NONE'
JUMPGE P1,COMERA## ;IF A NUMBER WAS TYPED WE SHOULDN'T BE HERE
JRST SETB10 ;GO CLEAR BREAK CONDITIONS
SETBR3: PUSHJ P,CTEXT## ;GET THE NEXT TEXT ARGUMENT
JUMPE T2,NOTENF## ;IF WE'RE HERE THERE HAS TO BE ONE
JRST .(P2) ;DISPATCH TO THE APPROPRIATE PROCESSOR
JRST SETBR4 ;USER TYPED 'AT'
JRST SETBR5 ;USER TYPED 'ON'
JRST SETBR6 ;USER TYPED 'NO'
;HERE WHEN THE USER TYPED 'AT'
SETBR4: JUMPGE P1,COMERA## ;NO PREVIOUS NUMBERS ALLOWED IF WE GET HERE
PUSHJ P,GETNUM ;CONVERT THE NUMBER FROM SIXBIT TO OCTAL
JRST COMERA## ;IT MUST BE A NUMBER BUT ISN'T SO COMPLAIN
JRST SETBR1 ;LOOK FOR THE NEXT TEXT ARGUMENT
;HERE WHEN THE USER TYPED 'ON'
SETBR5: SKIPA P1,[TDO P2,BRKTBL-1(T1)]
;HERE WHEN THE USER TYPED 'NO'
SETBR6: MOVE P1,[TDZ P2,BRKTBL-1(T1)]
.HLLZ P2,.PDABS##(W) ;GET CURRENT BREAK CONDITIONS
SETBR7: MOVE T1,[-7,,BRKLS2] ;TABLE LENGTH,,TABLE ADDRESS
PUSHJ P,FNDNAM## ;GET A BREAK CONDITION
JRST COMERA## ;IT CAN'T BE ANYTHING ELSE
JUMPE T1,SETB11 ;JUMP IF 'USERS'
CAIN T1,AFTERX
JRST SETB12
XCT P1 ;SET OR CLEAR THE CONDITION
PUSHJ P,CTEXT## ;GET THE NEXT ARGUMENT
JUMPN T2,SETBR7 ;LOOP BACK IF THERE WAS ONE
TLZ P2,(OC.ABE+OC.FUP) ;ASSUME NO CONDITIONS
TLNN P2,(OC.BCI+OC.BCD+OC.BCW+OC.BCM) ;ANY CONDITIONS DESIRED?
JRST SETB10 ;NO, DECREMENT NUMBER OF USERS USING ADDRESS BREAK
SETBR8: PUSHJ P,BRKAV ;SEE IF ADDRESS BREAK IS AVAILABLE AND INCREMENT
; THE COUNT OF USERS USING IT IF SO
JRST NOBRAK ;NOT AVAILABLE, COMPLAIN
SETBR9: TLOA P2,(OC.ABE+OC.FUP) ;ENABLE THE USER FOR ADDRESS BREAK
SETB10: PUSHJ P,BRKDEC ;DECREMENT THE COUNT OF USERS USING ADDRESS BREAK
.HLLM P2,.PDABS##(W) ;STORE THE NEW CONDITIONS
POPJ P, ;AND RETURN TO COMCON
;HERE WHEN THE USER TYPED 'USERS', MUST BE PRIVILEGED
SETB11: PUSHJ P,SETLGL## ;USER SUFFICIENTLY PRIVILEDGED TO MONOPOLIZE
; ADDRESS BREAK?
JRST COMERA## ;NO, COMPLAIN
PUSHJ P,FDNJP ;FIND THE NULL JOB'S PDB
MOVSI T2,400000 ;SET TO TURN ON OR OFF ADDRESS BREAK
CAME P1,[TDZ P2,BRKTBL-1(T1)] ;WAS 'USERS' WITHOUT A 'NO' TYPED?
JRST [.ANCAM T2,.PDABS##(T1) ;YES, ALLOW USERS TO USE ADDRESS BREAK
POPJ P,] ;RETURN
;HERE WHEN THE USER TYPED 'NO USERS'
.SKPLE .PDABS##(T1) ;IS ADDRESS BREAK CURRENTLY BEING USED?
JRST NOBRAK ;DON'T ALLOW HIM TO YANK IT OUT FROM UNDER THEM
.IORM T2,.PDABS##(T1) ;DON'T ALLOW USERS TO USE ADDRESS BRAEK
POPJ P, ;RETURN TO COMCON
;HERE WHEN THE USER TYPED 'AFTER'
SETB12: PUSHJ P,DECIN## ;GET THE NEXT ARGUMENT
PJRST NOTENF## ;THERE MUST BE ONE
JRST COMERA## ;NOTHING BUT A NUMBER IS LEGAL
CAILE T2,^D510 ;IS IT TOO BIG?
JRST COMERA## ;YES
ADDI T2,1
DPB T2,[POINT 9,P2,17] ;SAVE THE REPEAT COUNT
JRST SETB1A ;STORE IT AND GO AWAY
;HERE ON A SET ADDRESS BREAK UUO
SETABR::PUSHJ P,SAVE2## ;SAVE P1,P2
HRR M,T2 ;ADDRESS OF USER'S ARGUMENT
PUSHJ P,GETWDU## ;GET THE ARGUMENT
HRRM T1,.PDABS##(W) ;STORE THE BREAK ADDRESS
MOVE P2,T1 ;P2 = BREAK CONDITIONS
TLZ P2,(OC.FEP) ;HE ISN'T ALLOWED TO SET FOLLOW EXEC PAGING
TLO P2,(OC.BSU) ;INDICATE SET BY UUO
AOS (P) ;PREPARE TO GIVE GOOD RETURN
TLNN P2,(OC.BCI+OC.BCD+OC.BCW+OC.BCM)
JRST [PUSHJ P,SETB10 ;TURNING OFF BREAK
PJRST SETRL1]
PUSHJ P,BRKAV ;IS ADDRESS BREAK AVAILABLE?
SOSA (P) ;NO, ERROR RETURN
JRST [PUSHJ P,SETBR9 ;YES, SETUP BREAK CONDITIONS
PJRST SETRL1]
POPJ P, ;GIVE ERROR RETURN
;HERE ON RESET TO CLEAR BREAK ADDRESS AND CONDITIONS
; IF SET BY UUO
CLRBRK::SKIPE T1,.PDABS##(W) ;BREAK IN USE AT ALL?
TLNN T1,(OC.BSU) ;AND SET BY UUO?
POPJ P, ;NO
PUSHJ P,BRKDEC ;YES, DECREMENT COUNT OF USERS
SETZM .PDABS##(W) ;CLEAR ADDRESS AND CONDITIONS
POPJ P, ;AND RETURN
;THE ORDER OF AND THE NUMBER OF ENTRIES
; IN THE FOLLOWING TABLES CANNOT BE CHANGED
; WITHOUT CHANGING THE CODE IN SETBRK
BRKLS1: SIXBIT /NONE/
SIXBIT /AT/
SIXBIT /ON/
SIXBIT /NO/
BRKLS2: SIXBIT /USERS/
SIXBIT /EXECUT/
SIXBIT /READ/
SIXBIT /WRITE/
SIXBIT /MUUO/
SIXBIT /ALL/
BRKLS3: SIXBIT /AFTER/
AFTERX==BRKLS3-BRKLS2
;THE ENTRIES IN THIS TABLE CORRESPOND IN ORDER
; TO THE ENTRIES IN THE ABOVE TABLE
BRKTBL: EXP OC.BCI
EXP OC.BCD
EXP OC.BCW
EXP OC.BCM
EXP OC.BCI+OC.BCD+OC.BCW
;SUBROUTINE TO DETERMINE IF THE SIXBIT STRING IN
; T2 IS A LEGAL OCTAL NUMBER
;CALLING SEQUENCE:
;
; MOVE T2,SIXBIT STRING
; PUSHJ P,GETNUM
;NON-SKIP RETURN IF T2 DOES NOT CONTAIN A
; NUMBER, P1.LT.0, AND T2 PRESERVED
;SKIP RETURN P1=NUMBER IF T2 CONTAINS A NUMBER
;NEVER RETURNS IF T2 CONTAINS A MALFORMED
; NUMBER
;N.B. P1 MUST BE SAVED BEFORE CALLING THIS
;SUBROUTINE
GETNUM: MOVSI P1,400000 ;INDICATE NO NUMBER SEEN
MOVEI T3,0 ;CLEAR RESULT SO FAR
MOVE T4,[POINT 6,T2] ;BYTE POINTER TO PICKUP CHARACTERS
GETNM1: ILDB T1,T4 ;GET THE NEXT CHARACTER
CAIL T1,'0' ;IS THE CHARACTER .LT. ZERO?
CAILE T1,'7' ;OR G.GE. 7?
JRST GETNM2 ;YES, ITS NOT AN OCTAL DIGIT
LSH P1,3 ;MULTIPLY ACCUMULATED RESULT BY 8
ADDI P1,-'0'(T1) ;ADD IN THE CURRENT CHARACTER
JRST GETNM1 ;AND GET THE NEXT DIGIT
GETNM2: JUMPL P1,CPOPJ## ;NON-SKIP RETURN IF NOT A NUMBER
JUMPN T1,COMERP## ;NUMBERS WHICH TERMINATE WITH NON-DIGITS ARE
; NOT NUMBERS
JRST CPOPJ1## ;GIVE NUMBER FOUND RETURN
;SUBROUTINE TO DETERMINE WHETHER ADDRESS BREAK IS AVAILABLE TO USERS
;CALLING SEQUENCE:
; PUSHJ P,BRKAV
;NON-SKIP RETURN IF NOT AVAILABLE BECAUSE MEMORY
; INDICATORS ARE DISABLED OR ADDRESS BREAK IS BEING
; USED BY SYSTEM PROGRAMMERS FOR MONITOR DEBUGGING
;SKIP RETURN IF ADDRESS BREAK IS AVAILABLE TO USERS, COUNT OF THE NUMBER
;OF USERS USING ADDRESS BREAK HAS BEEN UPDATED
;PRESERVES T2
BRKAV: PUSHJ P,FDNJP ;FIND THE NULL JOB'S PDB
PUSHJ P,CP0RC## ;SEE IF THE JOB IS RUNNABLE ON CPU0
TLNN P2,(OC.BCM) ;ITS NOT, BUT IF HE IS ENABLED FOR UUOS, SOME
; MUST HAPPEN ON CPU0
SKIPGE .PDABS##(T1) ;HAS ADDRESS BREAK BEEN DISABGEED BY THE OPR?
POPJ P, ;YES, LOSE
.MOVE T3,.PDABS##(W) ;GET HIS CURRENT ADDRESS BREAK SETTINGS
TLNN T3,(OC.ABE) ;IS HE ALREADY BREAKING?
.AOS .PDABS##(T1) ;NO, COUNT UP THE NUMBER OF USERS USING ADDRESS BREAK
JRST CPOPJ1## ;AND GIVE THE HAPPY RETURN
;SUBROUTINE TO DECREMENT THE COUNT OF THE NUMBER
; OF USERS USING ADDRESS BREAK
BRKDEC: .MOVE T1,.PDABS##(W) ;GET HIS CURRENT BREAK SETTINGS
TLNN T1,(OC.ABE) ;IS HE ENABLED FOR ADDRESS BREAK?
POPJ P, ;NO, NOTHING TO DO
PUSHJ P,FDNJP ;FIND THE PDB FOR THE NULL JOB
.SOS .PDABS##(T1) ;DECREMENT THE COUNT OF USERS USING ADDRESS BREAK
POPJ P, ;AND RETURN
NOBRAK: PJSP T1,CONMES## ;SORRY FOLKS!
ASCIZ /?Not available
/
;SUBROUTINE TO RETURN THE ADDRESS OF THE NULL JOB'S PDB IN T1
;PRESERVES T2-T4
FDNJP: MOVEI T1,0 ;NULL JOB'S JOB NUMBER
PUSHJ P,FPDBT1## ;FIND THE NULL JOB'S PDB, RETURN ITS ADDRESS IN T1
JFCL ;IT MUST HAVE ONE
POPJ P, ;RETURN TO THE CALLER
> ;END IFN FTSET
SUBTTL IOCSS - I/O SERVICE SUBROUTINES (UUOCON AND DEVICE ROUTINES)
;ROUTINE TO DETERMINE WHETHER A DEVICE NEEDS THE USER AREA
;REPRESENTED IN THE CURRENT I/O OPERATION TO BE
;MAPPED IN EXEC VIRTUAL MEMORY
;CALLING SEQUENCE:
;
; MOVE F,ADDRESSS OF DEVICE DATA BLOCK
; PUSHJ P,MAPDEV
; RETURN HERE IF NO MAPPING REQUIRED
; RETURN HERE IF BUFFERS OR IOWDS MUST BE MAPPED
MAPDEV::PUSH P,T1 ;SAVE P1
MOVEI T1,DEPEVM ;GET "DEVICE DOESN'T NEED EVM" BIT
TDNN T1,DEVTYP(F) ;SKIP IF MAPPING NOT REQUIRED
PJRST TPOPJ1## ;PTY, TTY, AND CHANNEL DEVICES ARE NOT
; MAPPED IN EXEC VIRTUAL MEMORY
PJRST TPOPJ## ;ALL I/O BUS DEVICE REQUIRE MAPPING IN
; EXEC VIRTUAL MEMORY
;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
DATAI PAG,T1 ;GET THE USER AND EXEC BASE REGISTERS
PUSH P,J ;SAVE J
LDB J,PJOBN## ;GET THE JOB NUMBER OF JOB CURRENTLY USING
; THIS DEVICE
PUSHJ P,STEUB ;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
DATAI PAG,T1 ;GET THE CONTENTS OF THE USER AND EXEC BASE REGISTERS
PUSHJ P,STEUB ;SETUP THE UBR FOR THE JOB WHOSE JOB NUMBER
; IS IN J
JRST SSEU1 ;SAVE THE PREVIOUS CONTENTS OF THE UBR AND THE EBR
SSEUB: PUSH P,T1 ;SAVE A TEMPORARY
DATAI PAG,T1 ;GET THE CONTENTS OF THE USER AND EXEC BASE REGISTERS
SSEU1: DATAO APR,[0] ;NO ADDRESS BREAKS
EXCH T1,-1(P) ;GET THE CALLER'S PC AND SAVE THE CONTENTS
; OF THE UBR AND EBR
MOVEM T1,1(P) ;SAVE THE CALLER'S PC IN A TEMPORARY LOCATION
; ON THE STACK
POP P,T1 ;RESTORE T1 TO ITS CONTENTS ON ENTRY
PUSHJ P,@2(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 AND THE EBR
CAIA ;CPOPJ RETURN
AOS -1(P) ;CPOPJ1 RETURN - BUMP RETURN PC
EXCH T1,(P) ;GET THE PREVIOUS CONTENTS OF THE UBR
DATAO PAG,T1 ;RESTORE THE UBR AND THE EBR
MOVEI T1,.C0CDB## ;ASSUME CPU0
IFN FTMS,<
SKPCPU (0) ;IS IT?
MOVEI T1,.C1CDB## ;NO
>
DATAO APR,.CPAPR##(T1) ;ALLOW ADDRESS BREAKS NOW
JRST TPOPJ## ;RESTORE T1 AND RETURN
;ROUTINE TO MAP USER AREA IN THE EXEC MAP
;CALLING SEQUENCE:
;
; MOVE T1,PAGE NUMBER OF STARTING PAGE IN THE EXEC MAP
; MOVE T2,NUMBER OF PAGES
; MOVE T3,USER VIRTUAL ADDRESS
; PUSHJ P,MAPUEV
;OR
; PUSHJ P,MAPUEI IF AT INTERRUPT LEVEL SO EBR,UBR WILL BE
; RESTORED SO DO NOT NEED TO PURGE ASSOCIATIVE MEMORY
; RETURNS HERE - T1=PAGE NUMBER IN THE EXEC MAP, T3=EXEC VIRTUAL
; ADDRESS WHICH CORRESPONDS TO USER VIRTUAL ADDRESS,
; AND ASSOCIATIVE MEMORY IS PURGED
MAPUEV::PUSHJ P,SAVE3## ;SAVE P1-P3
PUSHJ P,MAPUE1 ;MAP THE USER IN EXEC VIRTUAL MEMORY
CAIE T2,1 ;DO WE NEED TO DO MORE
CLRPGT (0) ;RESET THE EXEC BASE REGISTER SO
; THE ASSOCIATIVE MEMORY WILL BE FLUSHED
; AND THE NEW MAPPING WILL BE IN EFFECT
POPJ P, ;RETURN
MAPUEI::PUSHJ P,SAVE3## ;SAVE P1-P3
MAPUE1: MOVE P1,T1 ;P1 = THE PAGE NUMBER OF THE FIRST PAGE
; IN THE EVM THAT BELONGS TO THIS JOB
SUBI P1,400 ;MAPPED ADDRESSES START AT 128K
ROT P1,-1 ;DIVIDE BY 2 AND PUT THE REMAINDER IN HIGH ORDER BIT
MOVEI P2,.EPPM##(P1) ;FORM A BYTE POINTER TO THE EXEC MAP
TLO P2,442200 ;ASSUME AN EVEN PAGE
SKIPGE P1 ;WAS IT EVEN?
HRLI P2,222200 ;NO, START WITH THE RIGHT HALF WORD
LDB P1,[POINT 9,T3,26]
ROT P1,-1 ;DIVIDE BY 2 AND PUT THE REMAINDER IN HIGH ORDER BIT
MOVEI P3,.UPMP(P1) ;FORM A BYTE POINTER TO THE USER'S MAP
SKIPL P1 ;FIRST PAGE EVEN
TLOA P3,442200 ;YES, THE FIRST PAGE IS MAPPED BY THE LEFT HALF WORD
HRLI P3,222200 ;NO, MAPPED BY THE RIGHT HALF WORD
MAPUE2: ILDB P1,P3 ;COPY A PORTION OF THE USER'S MAP TO
TRZ P1,760000 ;CLEAR ALL ACCESS BITS
TRO P1,PM.ACC+PM.WRT ;ACCESS ALLOWED, CONCEALED, AND WRITEABLE
IDPB P1,P2 ; THE EXEC MAP
SOJG T2,MAPUE2 ;COPY AS MANY PAGES AS ARE TO BE MAPPED IN EVM
DPB T1,[POINT 9,T3,26]
;FORM AN EXEC VIRTUAL ADDRESS FROM THE EXEC
; PAGE NUMBER AND THE USER VIRTUAL ADDRESS
POPJ P, ;RETURN
;ROUTINE TO MAP A USER BUFFER IN EXEC VIRTUAL MEMORY
;CALLING SEQUENCE:
; MOVE T1,BUFFER SIZE
; MOVE T3,USER VIRTUAL ADDRESS OF BUFFER
; MOVE F,ADDRESS OF THE DDB
; PUSHJ P,GTEVBF
; RETURN HERE ONLY IF REQUEST COULD NEVER BE SATISFIED (THERE WILL
; NEVER BE ENOUGH SLOTS AVAILABLE IN THE EXEC MAP)
; RETURN HERE - T1=BYTE (18)0(9) EXEC VIRTUAL PAGE # (9) # OF EXEC PAGES
; T3 = THE EXEC VIRTUAL ADDRESS OF THE BUFFER
GTEVBF::SUBI T1,2 ;COMPUTE THE UPPER BOUND ON THE NUMBER OF PAGES
IDIVI T1,PAGSIZ##+2 ; OF EXEC VIRTUAL MEMORY WHICH MIGHT BE
ADDI T1,2 ; REQUIRED TO COVER THIS BUFFER OR IOWD
CAMLE T1,EVBMAX## ;WILL THAT NUMBER OF PAGES EVER BE AVAILABLE?
POPJ P, ;NO, ERROR RETURN
PUSH P,T1 ;SAVE NUMBER OF PAGES BEING REQUESTED
GTEVB1: PUSH P,T3 ;SAVE THE USER VIRTUAL ADDRESS
PUSHJ P,GETEVM ;ATTEMPT TO GET ENOUGH PAGES TO SATISFY THE REQUEST
JRST GTEVBW ;NOT ENOUGH AVAILABLE (WAIT FOR SOME TO BE FREED UP)
POP P,T3 ;RESTORE THE USER'S VIRTUAL ADDRESS
MOVE T2,(P) ; AND THE NUMBER OF PAGES
PUSHJ P,MAPUEV ;MAP THE BUFFER OR IOWD IN THE EXEC MAP
MOVE T1,T3 ;T1 = EXEC VIRTUAL ADDRESS OF THE BUFFER OR IOWD
POP P,T2 ;MAKE T1 = EXEC VIRTUAL ADDRESS OF SAME
DPB T2,[POINT 9,T1,35]
JRST CPOPJ1## ;GIVE OK RETURN
GTEVBW: POP P,T3 ;RESTORE T3
PUSHJ P,EVWAIT## ;WAIT UNTIL SOME EVM IS FREED UP
MOVE T1,(P) ;RESTORE THE NUMBER OF PAGES REQUIRED
JRST GTEVB1 ;TRY AGAIN
;SUBROUTINE TO GET EXEC VIRTUAL MEMORY
;CALLING SEQUENCE:
;
; MOVE T1,NUMBER OF CONTIGOUS PAGES REQUIRED
; PUSHJ P,GETEVM
; ... ERROR RETURN - NOT ENOUGH AVAILABLE, T1 = LARGEST NUMBER SEEN
; ... OK RETURN - T1 = PAGE NUMBER OF FIRST AVAILABLE PAGE
GETEVM::MOVEI T2,EVMPTR## ;POINT TO EXEC-MAP USAGE TABLE
PUSHJ P,GETBIT## ;GET, SET BITS IN THE TABLE FOR THESE PAGES
POPJ P, ;NOT ENOUGH AVAILABLE, RETURN WITH T1= LARGEST HOLE
MOVEI T1,400(T1) ;MAKE RELATIVE LOCATION IN THE MAP INTO PAGE NUMBER
JRST CPOPJ1## ;AND GIVE SUCCESS RETURN
;ROUTINE TO GIVE BACK SLOTS IN THE EXEC MAP
;CALLING SEQUENCE:
; MOVE T1,NUMBER OF PAGES
; MOVE T2,EXEC VIRTUAL ADDRESS
; PUSHJ P,GIVEVM
; ALWAYS RETURN HERE
GIVEVM::LDB T2,[POINT 9,T2,26]
SUBI T2,400 ;CHANGE PAGE NUMBER INTO BIT POSITION
IDIVI T2,^D36 ;WHICH WORD
HRLS T2 ;PUT WORD NUMBER IN THE LEFT HALF
ADD T2,EVMPTR## ;MAKE AOBJN POINTER POINT TO THE WORD CONTAINING
; THE FIRST BIT TO CLEAR
PUSH P,T4 ;SETZRS CLOBBER T4
PUSHJ P,SETZRS## ;GIVE BACK THE EVM
PUSHJ P,EVFREE## ;WAKE UP ALL WAITERS FOR EVM
SETZM EVREQ## ;SO NEXT CALLER TO EVWAIT WILL WAIT (IMMEDIATELY)
JRST T4POPJ## ;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 IF DX10 CHL
; 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
MAPIO:: TLNN T2,-1 ;0 OR CHANNEL JUMPS ARE ILLEGAL
STOPCD CPOPJ,DEBUG,IEZ, ;++IOWD EQUALS ZERO
PUSHJ P,SVEUB ;SAVE AND SETUP UBR
PUSH P,U ;SAVE U
IFN FT22BIT,<
HLLZ U,CHB22B##(P3) ;GET CHANNEL-TYPE WORD
TLNE U,CP.RH2## ;RH20?
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 MAPIO9 ;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
MOVE T3,CHB22B##(P3)
TLNE T3,CP.RH2##
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 MAPIO8 ;NO MORE FOUR WORD BLOCKS
MOVE P4,-2(P) ;RESTORE THE IOWD TO P4
HRRZ T2,P4 ;ADDRESS-1 WHERE I/O WILL START
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 ;IS A DSK
CAIA
>
JRST MAPI1B
IFE FTVM<
SKIPL DEVSWP##(F) ;IF NOT THE SWAPPER
>
JUMPL S,MAPIO6 ; DONT UNRELOCATE IF MONITOR IO
MAPI1B: MOVE R,JBTADR##(J) ;ADDRESS OF THE JOB DATA AREA
PUSHJ P,CHKHS ;SEE IF A HIGH SEGMENT SAVE IS IN PROGRESS
IFE FTVM,<
CAIA
SKIPLE J,JBTSGN##(J) ;YES, J = HIGH SEGMENT NUMBER
SKIPN T1,JBTADR##(J) ;EXEC VIRTUAL ADDRESS OF THIS SEGMENT
; (DEVICE ROUTINES THINK THEY ARE RELOCATING
; THE IOWD BY ADDING THIS)
STOPCD .,JOB,IRE, ;++IOWD RELOCATION ERROR
CAILE J,JOBMAX## ;HIGH SEG?
MOVEI T1,342000 ;YES, USE STD ADDR
SUBI T2,-1(T1) ;SUBTRACT OUT "RELOCATION" AND ACCOUNT
; FOR THE FACT THAT IOWDS ARE ADDRESS-1
HRRZS T2 ;IN CASE OF MORE THAN 437 PAGES
LSH T2,W2PLSH## ;CONVERT TO PAGE NUMBER
PUSHJ P,SNPAGS ;GET THE ABSOLUTE PAGE NUMBER OF THIS PAGE
MOVE P3,T1 ;SAVE THAT IN P3
MOVE T2,P4 ;T2 AND P4 = IOWD+1
HLROS P4 ;P4 = -WORD COUNT
ADDI T2,1
MAPIO2: SKIPN T3,P3 ;T3 = CURRENT ABSOLUTE PAGE NUMBER
STOPCD .,JOB,APE, ;++ABSOLUTE PAGE EXCEEDED
; IOWD HAS BEEN ADDRESS CHECKED)
MOVEI T1,0 ;T1 = AMOUNT ACCUMULATED SO FAR
LSH T3,P2WLSH## ;MOVE PAGE NUMBER TO THE HIGH ORDER THIRTEEN
; BITS OF THE ADDRESS
ANDI T2,PG.BDY## ;GET THE STARTING WORD ADDRESS WITHIN THE PAGE
ADD T2,T3 ;T2 = ABSOLUTE ADDRESS
SUBI T2,1 ;MAKE T2 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,MAPIO4 ;JUMP IF THE ORIGIONAL WORD COUNT IS EXHAUSTED
IFN FT22BIT,<
SETZ T3, ;SET T3 SO TEST WILL FAIL IF 22-BIT CHAN AND
SKIPE U ; NO ROOM FOR ANOTHER PAGE IN THE IOWD
CAML T1,[EXP -37777+PAGSIZ##] ;OTHERWISE SET T3=CURRENT PAGE
>
MOVE T3,P3 ;T3 = CURRENT PAGE NUMBER WITHIN SEGMENT
HRRZ P3,PAGTAB(P3) ;P3 = NEXT PAGE NUMBER WITHIN SEGMENT
CAME T1,[-600000+PAGSIZ##] ;DONT GENERATE AN IOWD WHOSE WRDCNT
CAMN T1,[-30000+PAGSIZ##] ; LOOKS LIKE AN RH20 CHANNEL JUMP
JRST MAPI3A ; WORD
CAIN P3,1(T3) ;ARE THE TWO PAGES ADJACENT IN PHYSICAL MEMORY?
> ;END FTVM
IFN FTVM,<
JRST MAPI1C ;NO, GET VIRT ADR THE NORMAL WAY
MOVE T1,P4 ;YES, IOWD TO T1
SUBI T1,(R) ;UNRELOCATE IT
PUSHJ P,UVACK ;COMPUTE STARTING ADR FOR THIS PART
AOJA T2,MAPI1D ;AND CONTINUE
MAPI1C: SKIPN T1,JBTADR##(J) ;EXEC VIRTUAL ADDRESS OF THIS SEGMENT
; (DEVICE ROUTINES THINK THEY ARE RELOCATING
; THE IOWD BY ADDING THIS)
STOPCD .,JOB,IRE, ;++IOWD RELOCATION ERROR
SUBI T2,-1(T1) ;SUBTRACT OUT "RELOCATION" AND ACCOUNT
; FOR THE FACT THAT IOWDS ARE ADDRESS-1
HRRZS T2 ;NEEDED IF SEG GTR THAN 437 PAGES
MAPI1D: LSH T2,W2PLSH## ;CONVERT TO PAGE NUMBER
ROT T2,-1 ;SET UP A BYTE POINTER TO THE PAGE IN THE UPMP
ADDI T2,.UPMP
TLZE T2,400000
TLOA T2,(<POINT 18,0,35>)
TLO T2,(<POINT 18,0,17>)
MOVE P3,T2 ;SAVE POINTER IN P3
MOVE T2,P4 ;T2 AND P4 = IOWD
HLROS P4 ;P4 = -WORD COUNT
ADDI T2,1 ;POINT AT REAL ADR
MAPIO2: LDB T3,P3 ;T3 = CURRENT ABSOLUTE PAGE NUMBER
TRNN T3,PM.ACC
IFN FTEXE,<
SKIPGE USRHCU## ;IF A SAVE IS IN PROGRESS,
SKIPA ; THEN, THIS IS OK
>;END OF INF FTEXE
JRST S..AAO ;ACCESS ALLOWED OFF
; IOWD HAS BEEN ADDRESS CHECKED)
MOVEI T1,0 ;T1 = AMOUNT ACCUMULATED SO FAR
LSH T3,P2WLSH## ;MOVE PAGE NUMBER TO THE HIGH ORDER THIRTEEN
; BITS OF THE ADDRESS
ANDI T2,PG.BDY## ;GET THE STARTING WORD ADDDESS WITHIN THE PAGE
ADD 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,MAPIO4 ;JUMP IF THE ORIGIONAL WORD COUNT IS EXHAUSTED
IFN FT22BIT,<
SETZ T3, ;SET T3 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
>
LDB T3,P3 ;T3 = CURRENT PAGE NUMBER WITHIN SEGMENT
ILDB T4,P3 ;T4 = NEXT PAGE NUMBER WITHIN SEGMENT
TRNN T4,PM.ACC ;ACCESS ALLOWED ON?
STOPCD .,JOB,AAO, ;++ACCESS ALLOWED IS OFF
CAME T1,[-600000+PAGSIZ##] ;DONT GENERATE AN IOWD WHOSE LH
CAMN T1,[-30000+PAGSIZ##] ; LOOKS LIKE AN RH20 JUMP WORD
JRST MAPI3A
TRZ T3,760000 ;CLEAR ACCESS BITS
TRZ T4,760000 ;CLEAR OUT THE ACCESS BITS
CAIN T4,1(T3) ;ARE THE TWO PAGES ADJACENT IN PHYSICAL MEMORY?
> ;END IFN FTVM
JRST MAPIO3 ;YES, CONTINUE ON CURRENT IOWD
MAPI3A: MOVEI T2,0 ;T2 = FIRST ADDRESS
POP P,(P1) ;STORE THE IOWD ABSOLUTE ADDRESS
IFE FT22BIT,<
HRLM T1,(P1) ;AND THE WORD COUNT (NUMBER OF WORDS MAPPED SO FAR)
>
IFN FT22BIT,<
PUSHJ P,DXFIX ;ADJUST IOWD IF A DX10
JRST MAPIO8 ;NO SPACE
JUMPL U,MAPIO7 ;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 MAPIO8 ;WHOOPS! NONE AVAILABLE
MOVEI T2,0 ;START AT WORD NUMBER ZERO ON THIS PAGE
JRST MAPIO2 ;MAP THE REST OF THE IOWD
MAPIO4: POP P,(P1) ;STORE THE IOWD ABSOLUTE ADDRESS
ADD P4,T1 ;ADD THE RESIDUAL WORD COUNT TO THE ACCUMULATED
; WORD COUNT
IFE FT22BIT,<
HRLM P4,(P1) ;STORE WORD COUNT IN IOWD
>
IFN FT22BIT,<
MOVE T1,P4 ;PUT WD CNT INTO T1
PUSHJ P,DXFIX ;PERFORM FIXUPS FOR DX10
JRST MAPIO8 ;OUT OF SPACE
>
JRST MAPIO7 ;AND GIVE THE WIN RETURN
MAPIO6:
IFE FT22BIT,<
MOVEM P4,(P1) ;THE I/O IS INTO A MONITOR BUFFER SO STORE
>
IFN FT22BIT,<
MOVEM T2,0(P1) ;STORE ADDRESS
HLRE T1,P4 ;GET WORD COUNT
PUSHJ P,DXFIX ;FIDDLE WITH DX10 IOWDS
JRST MAPIO8 ;NO ROOM
>
; THE ALREADY ABSOLUTE IOWD AND RETURN
MAPIO7: 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
MAPIO8:
IFE FT22BIT,<
HLRE P4,-1(P1) ;GET NEG WORD CNT FROM LAST IOWD
HRRZ T1,-1(P1) ;GET START OF DATA FROM LAST IOWD
SUB T1,P4 ;DETERMINE ENDING DATA ADDRESS
HRL T1,P1 ;PUT ADDR OF END OF IOWD LIST
>
SKIPGE -3(P) ;IF WE WANT IT STORED,
TRNE U,5 ;TYPE 0 OR 2 OR 4 CONTROLLER?
JRST MAPIO9 ;NO, DON'T DO NEXT
IFN FT22BIT,<
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 P3,-3(P)
MOVEM T1,CHNTCW##(P3)
MAPIO9: 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 ITS AN RH20
MOVEI T3,177
ANDB T3,CHNTCW##(P3) ;NO SWEAT IF AN EVEN MULTIPLE OF 200 WORDS
JUMPE T3,RH2ND1
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:
IFN FT22BIT,<
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
IFN FT22BIT,<
;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
MOVEI T2,0 ;RESTORE T2
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
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
> ;END IFN FT22BIT
;ROUTINE TO HANDLE RH20 DEVICES
RH2FIX: SKIPE (P1) ;UNLESS THROW-AWAY IOWD
AOS (P1) ;RH20 LIKES ADDRESS
MOVNS T1 ; AND POSITIVE WRDCNT
MOVE T3,-4(P)
ADDM T1,CHNTCW##(T3) ;ACCUMULATE WDCNT
RH2FX1: CAIG T1,3000 ;IF LESS THAN 12 BITS,
JRST RH2FX3 ; DONT HAVE TO FIDDLE WITH IT
MOVEI T3,3000+RH2TRX## ;ONLY CAN DO 11 BITS IN ONE IOWD
DPB T3,WDCPNT##+3 ;SAVE THIS IOWD
SUBI T1,3000 ;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
ADDI T3,3000 ;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
;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::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
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
PJRST SETZRS## ;CLEAR THE BITS AND RETURN
;SUBROUTINE TO CHECK TO SEE IF THE CURRENT I/O OPERATION IS A
; HIGH SEGMENT SAVE
;CALLING SEQUENCE:
; MOVE F,DDB ADDRESS
; MOVE R,LOW SEGMENT ADDRESS
; PUSHJ P,CHKHS
; RETURN HERE IF NORMAL I/O
; RETURN HERE IF HIGH SEGMENT SAVE
CHKHS: PUSHJ P,SAVE1## ;SAVE P1
MOVE P1,DEVMOD(F) ;DEVICE DESCRIPTORS
TLNE P1,DVDSK ;DSK I/O?
SKIPL DEVSWP##(F) ;YES, SWAPPING I/O?
SKIPL P1,JOBHCU##(R) ;NO, IS A SAVE OR GET IN PROGRESS?
POPJ P, ;NOT SAVE/GET
TLNE P1,3 ;DOING THE I/O TO SAVE A HIGH SEGMENT?
POPJ P, ;NO, NORMAL I/O
IFN FTEXE,<
PUSH P,J ;SAVE J
LDB J,PJOBN## ;GET CURRENT JOB NUMBER
PUSHJ P,CHKEXE## ;IS THIS AN EXE FILE SAVE?
JRST JPOPJ## ;YES, EXIT AND DO NOTHING
POP P,J ;NO, RESTORE J
>;END OF IFN FTEXE
PJRST CPOPJ1## ;YES, GIVE HIGH SEGMENT SAVE IN PROGRESS RETURN
;SUBROUTINE TO RETURN THE USER VIRTUAL ADDRESS OF THE
; CHECKSUM WORD
;CALLING SEQUENCE:
; MOVE T1,IOWD TO BE USED IN THE FILE TRANSFER (UNRELOCATED)
; MOVE R,LOW SEGMENT PROTECTION,, RELOCATION
; PUSHJ P,UVACKS
; ALWAYS RETURN HERE - T2 = UVA OF THE CHECKSUM
;PRESERVES T1
UVACK:
UVACKS::HRRZ T2,T1 ;ADDRESS I/O WILL BE DONE FROM OR TO
PUSHJ P,CHKHS ;SEE IF SAVING A HIGH SEGMENT
POPJ P, ;NO, NORMAL I/O RETURN
SUBI T2,.VJDT-.JDAT ;T2=ADDRESS WITHIN THE HIGH SEGMENT WHERE
; OUTPUT WILL START
PUSH P,T2 ;SAVE THAT
PUSH P,J ;SAVE J
PUSH P,T1 ;AND T1
LDB J,PJOBN## ;GET JOB NUMBER
PUSHJ P,HSVAD## ;GET THE STARTING VIRTUAL ADDRESS OF THE
; HIGH SEGMENT
POP P,T1 ;RESTORE T1
POP P,J ;AND J
ADDM T2,(P) ;(P)=UVA OF FIRST WORD -1 TO BE OUTPUT
JRST T2POPJ## ;T2=UVA, AND RETURN
;SUBROUTINE TO GET EVM IF NEEDED FOR OUTPUT
;CALLING SEQUENCE:
; MOVE F,DDB ADDRESS
; PUSHJ P,GTOEVM
; RETURN HERE
;NEVER RETURN IF TO MUCH EVM IS REQUIRED
GTOEVM::SKIPA T3,PDVOAD## ;POINTER TO UVA OF THE BUFFER
; PJRST GTBEVM ;MAP THE BUFFER IN EVM
;SUBROUTINE TO GET EVM IF NEEDED FOR INPUT
;CALLING SEQUENCE:
; MOVE F,DDB ADDRESS
; PUSHJ P,GTIEVM
; RETURN HERE
;NEVER RETURN IF TO MUCH EVM IS REQUIRED
GTIEVM::MOVE T3,PDVIAD## ;POINTER TO UVA OF THE BUFFER
; PJRST GTBEVM ;MAP THE BUFFER IN EVM
;FALL INTO GTBEVM
;SUBROUTINE TO ACCOUNT FOR THE FACT THAT BUFFERS
; ARE TWO WORDS LONGER THAN THE NUMBER OF DATA
; WORDS IN THE BUFFER AND THE FACT THAT THE LINK
; WORD IS REALLY THE SECOND WORD OF THE BUFFER
;CALLING SEQUENCE:
; MOVE T3,POINTER TO THE CURRENT BUFFER (UVA)
; PUSHJ P,GTBEVM
; RETURN HERE T1 = # OF PAGES + STARTING PAGE #, T3 = EVA OF BUFFER
;NEVER RETURN IF NOT ENOUGH EVM
GTBEVM: PUSHJ P,MAPDEV ;IS CURRENT DEVICE A PTY, TTY, OR ON A CHANNEL?
POPJ P, ;YES, DO NOT ALLOCATE ANY EVM
PUSH P,T3 ;SAVE THE USER VIRTUAL ADDRESS OF THIS BUFFER
; SO CAN RETURN EVM ON HUNG DEVICE, ETC.
HRRZ T3,@T3 ;USER VIRTUAL ADDRESS OF THE BUFFER
EXCTUX <HLRZ T1,(T3)> ;SIZE OF THE BUFFER
TRZ T1,IOUSE ;T1 = NUMBER OF DATA WORDS - USE BIT
SUBI T3,1 ;POINT TO ACTUAL FIRST WORD OF THE BUFFER
ADDI T1,2 ;ACCOUNT FOR THE TWO OVERHEAD WORDS IN
; THE BUFFER
PUSHJ P,GTEVBF ;MAP THE BUFFER IN EVM - WAIT UNTIL
; SOME IS AVAILABLE IF NECESSARY
JRST ADRERR## ;NEVER WILL BE ENOUGH EVM
HRL T1,@(P) ;SAVE USER VIRTUAL ADDRESS OF THE BUFFER
ADDI T3,1 ;BUMP BUFFER ADDRESS TO THE LINK WORD
CONO PI,PI.OFF ;GUARD AGAINST INTERRUPTS
MOVEM T1,DEVEVM(F) ;SAVE THE STARTING PAGE NUMBER AND NUMBER
; OF PAGES OF EVM FOR ADVANCING BUFFERS
; AND RETURNING EVM
DPB T3,(P) ;STORE THE EVA OF THE BUFFER FOR THE DEVICE ROUTINE
CONO PI,PI.ON ;NOW, ALLOW INTERRUPTS AGAIN
JRST T2POPJ## ;RETURN
;SUBROUTINE TO RESTORE EVM AFTER GIVING IT
; UP ON A CALL TO THE SCHEDULER (CONTROL BUSY, HUNG DEVICE, ETC.)
;CALLING SEQUENCE:
; MOVE F,ADDRESS OF DEVICE DATA BLOCK
; MOVE S,DEVIOS(F) ;DEVICE STATUS
; PUSHJ P,RSTEVM
; RETURN HERE IF NO ADDRESS CHECK WITH DEVEVM(F) SETUP
RSTEVM::LDB T1,PIOMOD## ;GET DATA MODE
CAIL T1,SD ;DUMP MODE?
PJRST DMPEV ;YES, GET EVM DUMP MODE STYLE
TLNE S,IO ;BUFFERED MODE, INPUT OR OUTPUT?
PJRST GTOEVM ;OUTPUT, GET BUFFERED OUTPUT EVM
PJRST GTIEVM ;INPUT, GET BUFFERED INPUT EVM
;SUBROUTINE TO DETERMINE IF A DEVICE NEEDS EVM TO DO DUMP
; MODE I/O AND IF SO TO SCAN THE IOWD LIST TO FIND THE
; IOWD WHICH HAS THE LARGEST WORD COUNT AND ALLOCATE
; ENOUGH EVM TO COVER THAT IOWD.
;CALLING SEQUENCE:
; MOVE M,USER VIRTUAL ADDRESS OF IOWD LIST
; MOVE F,ADDRESS OF DEVICE DATA BLOCK
; PUSHJ P,DMPEV
; RETURN HERE IF NO ADDRESS CHECK WITH DEVEVM(F) SETUP
;PRESERVES T1
DMPEV::
PUSHJ P,SAVE4## ;SAVE P1-P4
IFN FTVM,<
PUSH P,U ;SAVE U
MOVEI U,0 ;ASSUME THE DEVICE DOES NOT REQUIRE EXEC VIRTUAL
; MEMORY TO DO I/O (DSK, MTA, TTY, PTY)
>
PUSHJ P,MAPDEV ;NOT A KA10, NEED EVM TO DO I/O?
IFE FTVM,<
POPJ P, ;EVM NOT REQUIRED (KA10, CHANNEL DEVICE, TTY, OR PTY)
>
IFN FTVM,<
TLO U,400000 ;EVM NOT REQUIRED - SET U NEGATIVE
>
PUSH P,T1 ;SAVE DISPATCH ADDRESS
PUSH P,M ;SAVE THE UUO FOR THE DEVICE ROUTINE
SOS M ;COMPENSATE FOR GETWD1
MOVEI P2,0 ;LARGEST WORD COUNT SEEN SO FAR
MOVEI P3,10000 ;GUARD AGAINST A LOOP (GOTO IOWDS)
DMPEV1: PUSHJ P,GETWD1## ;GET AN IOWD
JUMPE T1,DMPEV4 ;JUMP IF LAST IOWD IN THE LIST
HLRO P1,T1 ;THIS IOWD'S WORD COUNT
TLNE T1,-1 ;A GOTO WORD?
JRST DMPEV2 ;NO, A REAL IOWD
HRRI M,-1(T1) ;A GOTO WORD (POINTS TO THE NEXT IOWD)
JRST DMPEV3 ;GET NEXT IOWD
DMPEV2: MOVNS P1 ;P1 = POSITIVE WORD COUNT FOR THIS IOWD
CAMLE P1,P2 ;GREATER THAN THE LARGEST WORD COUNT SEEN SO FAR?
MOVE P2,P1 ;YES, REMEMBER IT AS LARGEST SEEN
IFN FTVM,<
PUSHJ P,CHKHS ;HIGH SEGMENT SAVE?
JRST DMPE2A ;NO
PUSH P,T1 ;YES, SAVE IOWD
PUSHJ P,HSVAD## ;GET START ADR OF HI SEG
POP P,T1 ;RESTORE START ADR OF IOWD
ADDI T1,-1000(T2) ;POINT TO START OF HIGH SEG
DMPE2A: MOVEI T1,1(T1) ;START ADR OF THE IOWD
MOVE T2,P1 ;TOP ADR OF THE IOWD
ADDI T2,-1(T1)
PUSHJ P,TRNGE## ;MAKE SURE THE REQUIRED PAGES ARE IN CORE
>
DMPEV3: SOJG P3,DMPEV1 ;GET NEXT IOWD IN THE LIST
JRST ADRERR## ;TOO MANY IOWDS (PROBABLY A GOTO WORD LOOP,
; STOP THE JOB AND REPORT THE ERROR)
DMPEV4: POP P,M ;RESTORE THE UUO AND THE POINTER TO THE FIRST
; IOWD IN THE LIST
IFN FTVM,<
JUMPL U,DMPEV5 ;DONT ACTUALLY NEED EVM IF U NEGATIVE
>
PUSHJ P,GETWDU## ;GET THE FIRST IOWD IN THE LIST AGAIN
HRRZ T3,T1 ;USER VIRTUAL ADDRESS WHERE I/O WILL START
MOVE T1,P2 ;NUMBER OF WORDS OF EXEC VIRTUAL MEMORY REQUIRED
; TO COVER THE LARGEST IOWD FOUND IN THE IOWD
; LIST
PUSHJ P,GTEVBF ;GET ENOUGH EVM TO COVER THE LARGEST WORD IN
; THE LIST (WAIT UNTIL AVAILABLE IF NECESSARY)
JRST ADRERR## ;WHOOPS! NEVER WILL BE ENOUGH
MOVEM T1,DEVEVM(F) ;DEVEVM = BYTE (18)0(9)EV PAGE #(9)# OF PAGES
IFE FTVM,<
PJRST TPOPJ## ;RESTORE T1 AND RETURN
>
IFN FTVM,<
DMPEV5: POP P,T1 ;RESTORE DISPATCH ADDRESS
JRST UPOPJ## ;RESTORE U AND RETURN
>
;ROUTINE TO RETURN ANY EVM A DEVICE MAY HAVE WHEN A SHARABLE RESOURCE
; WHICH CURRENTLY BELONGS TO THE JOB WHICH HAS THE DEVICE IS GIVEN UP.
;CALLING SEQUENCE:
; MOVE F,ADDRESS OF DEVICE DATA BLOCK OR 0 IF NONE
; PUSHJ P,RTEVM
;ALL ACS ARE RESPECTED.
RTEVM:: SKIPE F ;IS THIS A RESOURCE ASSOCIATED WITH I/O?
; I.E., IS THERE A DEVICE DATA BLOCK?
SKIPN DEVEVM(F) ;DOES THE JOB HAVE EVM?
POPJ P, ;NO, JUST RETURN
PUSHJ P,SAVT## ;IT IS THE TRADITION NOT TO CLOBBER ACS HERE
HRRZ T1,P
CAMG T1,SYSSIZ## ;DON'T CHANGE UBR IF P POINTS TO USER
PUSHJ P,SVEUF ;SAVE THE UBR AND SET IT UP SO CAN ADDRESS CURRENT JOB
PJRST RTNEVM ;GIVE UP EVM FOR MAPPING I/O IF ANY
;HERE TO GIVE UP EVM THAT THIS DEVICE HAS FOR INPUT OPERATIONS
RTEVMI::HLRZ T3,DEVEVM(F) ;USER VIRTUAL ADDRESS OF CURRENT BUFFER
JUMPE T3,CPOPJ## ;ZERO MEANS NO EVM REQUIRED FOR THE I/O
HRLI T3,R ;LITE R IN THE LEFT HALF TO SIGNAL USER
; VIRTUAL ADDRESS
PJRST RTIEVM ;GIVE BACK THE EVM
;HERE TO GIVE UP EVM THAT THIS DEVICE HAS FOR OUTPUT OPERATIONS
RTEVMO::HLRZ T3,DEVEVM(F) ;USER VIRTUAL ADDRESS OF CURRENT BUFFER
JUMPE T3,CPOPJ## ;ZERO MEANS NO EVM REQUIRED FOR THE I/O
HRLI T3,R ;LITE R IN THE LEFT HALF TO SIGNAL USER
; VIRTUAL ADDRESS
PJRST RTOEVM ;GIVE BACK THE EVM
;ROUTINE TO RETURN SLOTS IN THE EXEC MAP USED TO MAP USER BUFFERS
;CALLING SEQUENCE:
;
; MOVE T3,USER VIRTUAL ADDRESS OF BUFFER
; PUSHJ P,RTNEVM
; ALWAYS RETURN HERE
RTNEVM::MOVS T3,DEVEVM(F) ;ANY EVM ALLOCATED TO THIS DEVICE?
JUMPE T3,CPOPJ## ;NO, JUST RETURN
TRNN T3,-1 ;DUMP MODE I/O?
JRST RTNEV1 ;YES, DON'T CLOBBER DEVXAD
HRLI T3,R ;LITE R IN THE LEFT HALF TO SIGNAL THAT
; DEVIAD/DEVOAD NOW CONTAINS A USER VIRTUAL ADDRESS
TLNN S,IO ;OUTPUT?
JRST RTIEVM ;NO, GO RETURN INPUT EVM
RTOEVM::DPB T3,PDVOAD## ;STORE UVA IN DEVOAD
JRST RTNEV1 ;RETURN EVM
RTIEVM::DPB T3,PDVIAD## ;STORE UVA IN DEVIAD
RTNEV1: HRRZ T2,DEVEVM(F) ;PAGE NUMBER AND NUMBER OF PAGES OF EVM
LDB T1,[POINT 9,T2,35]
SETZM DEVEVM(F) ;FLAG NO LONGER ANY EVM
PJUMPN T1,GIVEVM ;RETURN THE EVM TO THE FREE POOL AND TELL
; THE SCHEDULAR THAT EVM IS AVAILABLE IF ANY
; JOB IS WAITING FOR SOME
POPJ P, ;RETURN
;ROUTINE TO CALL THE SCHEDULER AND REMEMBER IF A JOB HAS EVM OR NOT.
; IF SO, RESTORE THE EVM WHEN THE JOB BECOMES RUNNABLE AGAIN.
;PRESERVES ALL ACS
RMEVM:: SKIPE F ;IS THERE A DDB?
SKIPN DEVEVM(F) ;AND DOES IT HAVE EVM?
PJRST WSCHD1## ;NO--JUST RESCHEDULE
TRNE S,IOACT ;DON'T RETURN EVM IF THE DDB
JRST WSCHD1## ; IS I/O ACTIVE
PUSHJ P,RTEVM ;YES--RETURN THE EVM SINCE JOB MAY GET SWAPPED
PUSHJ P,WSCHD1## ;RESCHEDULE
PUSHJ P,SAVT## ;SAVE T2-T4
PJRST RSTEVM ;RESTORE THE EVM
;AND RETURN TO THE CALLER
;ROUTINE TO ADVANCE A BUFFER IN EXEC VIRTUAL MEMORY
;CALLING SEQUENCE:
;
; MOVE T3,XWD NEXT BUFFER SIZE,NEXT USER VIRTUAL BUFFER ADDRESS
; RETURN HERE IF NOT ENOUGH PAGES ALLOCATED IN EXEC MAP TO ADVANCE BUFFER
; RETURN HERE - BUFFER ADVANCED
; T1 = EXEC VIRTUAL ADDRESS OF BUFFER
; T3 = USER VIRTUAL ADDRESS OF BUFFER
ADVEVM::PUSH P,T3 ;SAVE BUFFER SIZE,,BUFFER ADDRESS
HRRZ T1,DEVEVM(F) ;BYTE (18)0(9) EXEC VIRTUAL PAGE #(9)# OF EXEC PAGES
HRLM T3,DEVEVM(F) ;STORE UVA OF NEXT BUFFER
HLRZ T2,T3 ;GET BUFFER SIZE
;DON'T NEED TO SUBTRACT 2 SINCE THE BUFFER IS ACTUALLY
; TWO WORDS LONGER THAN THE NUMBER OF DATA WORDS IT CONTAINS
; SUBI T2,2 ;COMPUTE THE UPPER BOUND ON THE NUMBER
IDIVI T2,PAGSIZ##+2 ; OF PAGES WHICH MAY BE REQUIRED TO
ADDI T2,2 ; MAP THIS BUFFER IN EXEC VIRTUAL MEMORY
LDB T3,[POINT 9,T1,35]
CAMLE T2,T3 ;DOES THE DEVICE HAVE A ENOUGH EVM TO MAP THIS BUFFER?
JRST T3POPJ## ;NO, STOP THE I/O (ENOUGH PAGES WILL BE
; AQUIRED THE NEXT TIME AROUND AT UUO LEVEL)
LDB T1,[POINT 9,T1,26]
HRRZS T3,(P) ;T3 = USER VIRTUAL ADDRESS OF THE NEXT BUFFER
SOS T3 ;T3 = ADDRESS OF FIRST WORD OF THE BUFFER
PUSHJ P,MAPUEV ;MAP THE NEXT BUFFER IN THE EXEC MAP
EXCH T3,(P) ;RESTORE THE USER VIRTUAL ADDRESS OF THE
; BUFFER IN CASE I/O MUST BE STOPPED FOR
; SOME OTHER REASON
AOS (P) ;BUMP BUFFER POINTER TO THE LINK WORD
PJRST TPOPJ1## ;T1 = EXEC VIRTUAL ADDRESS OF THE BUFFER
;ROUTINE TO INVALIDATE ENTIRE CACHE AND VALIDATE CORE
; ALWAYS RETURN CPOPJ, SAVING ALL T ACS.
; LOOP IN ACS WHILE WAITING FOR FLUSH COMPLETION TO MINIMIZE
; MEMORY INTERFERENCE.
CSDMP:: PUSHJ P,SAVT ;SAVE T ACCUMULATORS
DMOVE T1,CSHWAT ;CACHE WAITING INSTRUCTIONS
MOVE T3,CSHWT1
SWPUA ;SWEEP - UPDATE ALL PAGES, INVALIDATE CACHE
JSP T4,T1 ;WAIT IN ACS
POPJ P, ;RETURN
CSHWAT: CONSZ APR,LP.CSB ;WAIT FOR CACHE SWEEP TO HAPPEN
JRST T1
CSHWT1: JRST (T4) ;RETURN TO CALLER
IFN FTMS,<
;SUBROUTINE TO CHASE A LINE OUT OF THE CACHE
;ENTER T1=ADDRESS
;EXIT WITH THAT LOCATION NOT IN THE CACHE
;PRESERVES T2-T4
OUCHE:: TRZ T1,777000 ;GET LINE NUMBER
SKIP MONORG(T1) ;REFERENCE 4 CACHED PAGES WITH THAT LINE
SKIP MONORG+1000(T1) ; TO GET RID OF THE LINE
SKIP MONORG+2000(T1)
SKIP MONORG+3000(T1)
POPJ P,
>
SUBTTL SEGCON - SEGMENT CONTROL MODULE
;ROUTINE TO SAVE THE ABSOLUTE ADDRESS OF A HIGH SEGMENT AND RETURN
; ITS VIRTUAL ADDRESS (CALLED FROM REMAP)
; J=HI SEG NUMBER
; T1=NEW HI SIZE
; T2=WHERE,, NEW LOW SIZE
NEWHGH::PUSHJ P,SAVE3## ;SAVE P1-P3
HRRZ P2,T2 ;SAVE WHERE,,NEW LOW SEGMENT SIZE
HLRZS T2 ;WHERE TO PUT THE HIGH SEGMENT
ANDI T2,777000 ;MAKE SURE ITS ON A PAGE BOUNDARY
JUMPN T2,NEWHG0 ;JUMP IF HIGH SEGMENT STARTING ADDRESS SPECIFIED
TRNE P2,400000 ;IS THE LOW SEGMENT BIGGER THAN 128K?
SKIPA T2,P2 ;YES, HIGH SEGMENT ORIGIN IS FIRST PAGE ABOVE
; THE LOW SEGMENT
MOVEI T2,377777 ;NO, HIGH SEGMENT GOES AT 400000
MOVEI T2,1(T2) ;HIGH SEGMENT ORIGIN (ALSO CLEAR LEFT HALF OF T2)
NEWHG0: MOVE P3,.C0JOB## ;CURRENT JOB NUMBER
MOVEM R,JBTADR##(P3) ;STORE PREVIOUS PROTECTION,,JDAT IN CASE OF ERROR
IFN FTVM,<
MOVEI T3,1(T1) ;NUMBER OF WORDS IN NEW HIGH SEGMENT
MOVEI T1,1(P2) ;ADDRESS WHERE REMAP STARTS
LSHC T1,W2PLSH## ;T1=FROM PAGE, T2=TO PAGE
LSH T3,W2PLSH## ;NUMBER OF PAGES
HLRZ T4,SGAEXT##(R) ;FILE EXTENSION
SUBI T4,'SHR' ;T4=0 IF THE HIGH SEGMENT IS SHARABLE
PJRST NREMAP## ;REMAP IT
>
IFE FTVM,<
JUMPLE T2,CPOPJ## ;DON'T ALLOW HIGH SEGMENT AT PAGE ZERO
HRRZ P1,T1 ;NEW HIGH SEGMENT SIZE
ADDI P1,(T2) ;HIGH SEGMENT SIZE PLUS WHERE IT STARTS
TLNN P1,-1 ;WILL THE END OF THE HIGH SEGMENT BE OUTSIDE
; OF THE USER'S ADDRESSING SPACE? (.GT. 256K)
CAIG T2,(P2) ;OR WILL THE LOW SEGMENT AND HIGH SEGMENT OVERLAP?
POPJ P, ;YES, LOSE
HRLM P2,JBTADR##(P3) ;STORE NEW HIGHEST ADDRESS IN THE LOW SEGMENT
HRLI T1,.VJDT ;EXEC VIRTUAL ADDRESS OF THE VESTIGUAL JOB
; DATA AREA
LSH T2,W2PLSH## ;CONVERT HIGH SEGMENT ADDRESS TO PAGE NUMBER
DPB T2,JBYHSO## ;STORE ORIGIN OF THE HIGH SEGMENT
ROT P2,W2PLSH##-1 ;CONVERT TO PAGE NUMBER AND ODD OR EVEN PAGE
; IN THE HIGH ORDER BIT
TRZ P2,400000 ;DON'T LET BIT 8 OF USER-SPECIFIED
; HISEG ORIGIN SPILL OVER
MOVEI P1,.UPMP(P2) ;ADDRESS OF THE WORD IN THE MAP WHICH CONTAINS
; THE ABSOLUTE PAGE NUMBER OF THE LAST PAGE
; OF THE LOW SEGMENT
HRLI P1,222200 ;ASSUME AN EVEN PAGE NUMBER (I.E., MAPPED BY THE
; LEFT HALF WORD)
SKIPGE P2 ;IS IT EVEN?
HRLI P1,002200 ;NO, ODD - MAPPED BY THE RIGHT HALF WORD
LDB P2,P1 ;GET ABSOLUTE PAGE NUMBER OF LAST PAGE IN
; THE LOW SEGMENT
TRZ P2,760000 ;CLEAR ACCESS BITS
HLLZS PAGTAB(P2) ;INDICATE LAST PAGE IN THE LOW SEGMENT IN PAGTAB
ILDB T2,P1 ;GET THE ABSOLUTE PAGE NUMBER OF THE FIRST
; PAGE IN THE HIGH SEGMENT
DPB T2,JBYHSA## ;STORE IT FOR MAPPING THIS HIGH SEGMENT INTO
; FUTURE USER'S ADDRESSING SPACES
TRO T2,PM.ACC+PM.WRT+PM.CSH ;ACCESS ALLOWED AND WRITABLE
HRLM T2,.UPMP+.MVJDT ;MAP .VJDT IN THE PER-PROCESS MAP
JRST CPOPJ1## ;GIVE OK RETURN (HIGH SEGMENT WON'T OVERLAP
; LOW SEGMENT
>
;ROUTINE TO MAKE ANY WORD OF ANY JOB ADDRESSABLE
; (IN FACT WRITABLE) BY MAPPING IT THROUGH THE
; PER PROCESS MAP OF THE CURRENT JOB
;CALLING SEQUENCE:
; MOVE T2,USER VIRTUAL ADDRESS TO BE MAPPED
; MOVE J,JOB NUMBER OF JOB CONTAINING THE WORD
; PUSHJ P,MAPWRD
;OR PUSHJ P,MAPHC ;TO MAP JOBHCU
; ... RETURN HERE
;ON RETURN FROM CALL TO MAPWRD T2=EVA OF WORD
;ON RETURN FROM CALL TO MAPHC R=JOBHCU
;MAPHC PRESERVES T2
MAPHC:: PUSH P,T2 ;SAVE T2
IFE FTVM,<
MOVEI T2,0 ;JOB DATA AREA STARTS AT USER 0
>
IFN FTVM,<
MOVSI T2,1 ;UVA OF THE UPMP
>
PUSHJ P,MAPWRD ;MAKE THE JOB DATA AREA ADDRESSABLE
IFE FTVM,<
HRR R,T2 ;RH(R)=EVA OF JOB DATA AREA
>
IFN FTVM,<
HRRI R,.JDAT-.UPMP(T2)
>
JRST T2POPJ## ;RESTORE T2 AND RETURN
MAPWRD::
PUSHJ P,SCPCDB## ;POINT P4 AT THIS CPUSCDB
PUSH P,T2 ;SAVE UVA
ROT T2,W2PLSH##-1 ;CONVERT TO PAGE #/2 - REMAINDER IN HIGH BIT
MOVEI T1,.TEMP(T2) ;T1=ADDRESS OF TEMP. PP SLOT
HRLI T1,222200 ;ASSUME WORD IN EVEN PAGE
SKIPGE T2 ;IS IT?
HRLI T1,002200 ;NO - ODD PAGE
HRRZ T2,JBTUPM##(J) ;ADDRESS OF TARGET JOB'S UPMP
TRO T2,PM.ACC+PM.WRT;INSURE ACCESS ALLOWED
HRRM T2,.UPMP+.MTEMP ;MAKE THE TARGET JOB'S UPMP ADDRESSABLE
CLRPGT (0,.TEMP) ;CLEAR THE AM SO MAP WILL BE LOOKED
; AT NEXT.
LDB T2,T1 ;GET MAPPING FOR PAGE CONTAINING WORD
TRO T2,PM.ACC+PM.WRT;MAKE SURE CAN WRITE
HRRM T2,.UPMP+.MTEMP ;MAKE THE WORD ADDRESSABLE
CLRPGT (0,.TEMP) ;CLEAR AM FOR THIS PAGE
MOVEI T1,.TEMP/1000 ;PAGE # IN EV ADDRESSING SPACE
DPB T1,[POINT 9,(P),26] ;EVA OF WORD
JRST T2POPJ## ;RESTORE EVA AND RETURN
;ROUTINE TO MAKE AVAILABLE A PAGE MAP SLOT IN EVA SPACE
;MAY ONLY BE CALLED AT INTERUPT LEVEL
;CALLING SEQUENCE:
; MOVE P4,ADR OF CPU DATA BLOCK
; PUSHJ P,MAPLOC
; RETURN HERE
; C(T1) := BYTE PNTR TO EPMP SLOT
; C(T3) := RELATIVE PAGE # IN EPMP
MAPLOC::CONI PI,T1 ;GET PIS IN PROGRESS
ANDI T1,II.IPA ;CLEAR ALL BITS EXCEPT PIS IN PROGRESS
JFFO T1,.+2 ;FIND OUT THE HIGHEST PI IN PROGRESS, I.E.,
; THE ONE THAT THIS CODE IS BEING EXECUTED AT
STOPCD .,STOP,NPP, ;++NO PI IN PROGRESS
; NO PAGE IN THE EXEC MAP FOR MAPPING THE SCAN
SUBI T2,25 ;T2=0-6 FOR PI 1-7 IN PROGRESS
MOVE T3,T2 ;CALCULATE THE EXEC VIRTUAL ADDRESS FOR
LSH T3,P2WLSH## ; USE IN THE SWEEP RELATIVE TO PI TEMPORARIES.
ROT T2,-1 ;DIVIDE BY 2 AND PUT THE REMAINDER IN HIGH ORDER BIT
MOVEI T1,.MERPL(T2)
ADD T1,.CPTOS##(P4) ;T1=ADDRESS IN THE MAP OF SLOT USED FOR SCAN
HRLI T1,(<POINT 18,0,17>) ;ASSUME LEFT HALF WORD
SKIPGE T2 ;IS IT AN ODD PAGE?
HRLI T1,(<POINT 18,0,35>) ;YES, THEN ITS THE RIGHT HALF WORD
POPJ P, ;RETURN
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: MOVE P4,ADR OF CPU DATA BLOCK
; PUSHJ P,@.CPMPS##(P4)
; 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
IFN FTMEMPAR,< ;MEMORY PARITY ANALYSIS
XP PARDLY,20 ;NO. OF SOJ INSTR. TO DELAY SO PARITY CAN BE TESTED
CPLMPS::PUSHJ P,SAVE4## ;SAVE P1-P4 FOR BAD ADR. CONTENTS AND WORKING ACS
PUSHJ P,MAPLOC ;GET EXEC MAP SLOT
PUSH P,T1 ;SAVE BYTE POINTER TO EXEC MAP SLOT
MOVEI P1,0 ;SCAN ALL OF MEMORY STARTING WITH FAST ACS
; FOR CONVENIENCE (KI10 ALWAYS HAS FAST ACS)
MOVEI P3,PM.ACC+PM.WRT
;START AT PAGE 0. PAGE ATTRIBUTES TO ALLOW
; ACCESS AND WRITING (TO ATTEMPT REPAIR BELOW)
SETOM .CPPSP##(P4) ;FLAG THAT WE ARE IN A PARITY SWEEP (FOR TRAP ROUTINE)
LDB T4,[POINT 14,MEMSIZ##,26]
;T4=NUMBER OF PAGES TO SCAN (AVOID NXM)
SKIPA U,[POINT 1,NXMTAB##] ;BYTE POINTER TO TABLE REFLECTING EXISTANT MEMORY
MPSLP1: AOS P3 ;STEP TO NEXT PAGE
SOJL T4,MPSLP5 ;RESTORE T1 AND RETURN IF SCANNED ALL OF MEMORY
ILDB T1,U ;DOES THIS PAGE EXIST?
JUMPN T1,MPSLP1 ;JUMP IF NOT TO AVOID REFERENCING NON-EXISTANT
; PAGE
MOVEI P1,.ERPIL(T3) ;START AT THE BEGINNING OF THE PAGE
DPB P3,(P) ;MAP THE CURRENT PAGE
CLRPGT (P4) ;CLEAR THE ASSOCIATIVE SO THE NEW
; WILL BE USED
MOVEI T2,1 ;1 BLT/PAGE
MOVEI P2,PG.BDY##(P1) ;END OF BLT RANGE
HRL P1,P1 ;BLT TO SELF
MPSLP2:
;SPECIAL INSTRUCTION ADDRESS - REFERENCE MEMORY TO SEE IF BAD
XP CPLMPI,MPI+3 ;PC VALUE WHEN APR GETS PARITY INT.
;USED BY APR PI ROUTINE TO MAKE INSTR. SKIP
CONO PI,PIOFF ;TURN OF THE PI SYSTEM
MOVEI T1,@.CPEBR##(P4) ;GET EBR
TRZ T1,LG.CSL+LG.CSW ;TURN OF LOOK + LOAD
CONO PAG,@T1 ;SO WE CAN REFERENCE MEMORY WITHOUT THE CACHE
SETOM .CPPSP##(P4) ;SET SWEEPING FLAG IN MEMORY BECAUSE
;TRAP OCCURS WITH CACHE OFF!
CONSZ PI,@.CPAPP##(P4) ;APR PI IN PROGRESS (I.E. SCANNING
; AT APR INTERRUPT LEVEL?
TDZA T1,T1 ;YES, DON'T WAIT AT THE SOJG.
MOVEI T1,PARDLY ;NO. OF SOJ TO INSURE PARITY FLAG INT. OR ON
MPI: BLT P1,(P2) ;DOES THIS PAGE HAVE BAD PARITY?
CONO PAG,@.CPEBR##(P4) ;TURN THE CACHE BACK ON
CONO PI,PION ;AND ALSO THE PI SYSTEM
SOJG T1,. ;DELAY HERE SO APR INT. WILL OCCUR WITH
; PC AT A KNOWN PLACE IN MONITOR
JRST [IFN FTMEMNXM,<
TRNN S,UE.PEF
JRST [CONSO APR,LP.NXM
JRST MPSLP4
CONO APR,LP.CSF!LP.NXM
JRST MPSLP3]>
CONSO APR,LP.PAR
SKIPE .CPPTH##(P4) ;DID A PARITY TRAP HAPPEN?
SKIPA ;EITHER TRAP OR INTERRUPT HAPPENED
JRST MPSLP4
CONO APR,LP.CSF!LP.PAR!LP.SBE
JRST .+1]
;HERE ON BAD WORD FOUND (NXM OR PARITY) - APR OR PI 7 (APR INTERRUPT ADDED 2 TO PC)
IFN FTMEMNXM,<
TRNE S,UE.PEF ;A PARITY ERROR?
>
SETZM (P1) ;FIX UP BAD PARITY, BUT DON'T ATTEMPT
; TO STORE OLD CONTENTS, AS THE AR
; PARITY TRAP MAKES IT IMPOSSIBLE FOR
; THE SKIP INSTRUCTION TO COMPLETE
MPSLP3: PUSH P,T1
PUSH P,T2
MOVSI T1,DMACLR ;NOW CLEAR THE ERROR BITS INT THE DMA
SBDIAG T1 ;WITH FUNCTION 0
POP P,T2
POP P,T1
MAP T1,(P1) ;GET THE ADDRESS WHICH
; CORRESPONDS TO THE EXEC VIRTUAL ADDRESS IN P1
PUSH P,P2 ;SAVE THE END OF PAGE AC
PUSH P,P1 ;SAVE THE EVA
PUSH P,T3 ;SAVE THE POSITION IN THE MAP
PUSH P,T2
PUSH P,T4 ;SAVE # OF PAGES TO SCAN
LDB P1,[POINT 22,T1,35]
; P1=ABSOLUTE ADDRESS OF THE WORD WITH BAD PARITY
PUSHJ P,CPLASN ;YES, CONVERT TO SEG NUMBER, (J), REL ADR (T1)
SETOM T1 ;FLAG ABS. ADR NEITHER IN MONITOR NOR A SEGMENT.
MOVE P2,.CPTBD##(P4) ;GET BAD DATA WORD STORED BY THE TRAP ROUTINE
;FOR ERROR REPORTING
PUSHJ P,PARRBD## ;RECORD BAD DATA (T1=REL ADR, P1=BAD ADR,P2=
; BAD CONTENTS)
POP P,T4 ;RESTORE T4
POP P,T2 ; AND T2
POP P,T3 ; AND T3
POP P,P1 ; AND P1
POP P,P2 ; AND P2
SETZM .CPPTH##(P4) ;CLEAR FLAG THAT TRAP HAPPENED
AOS P1 ;INCREMENT TO ADDR
HRL P1,P1 ;AND THE FROM ADDR
JRST MPSLP2 ;AND CONTINE THE BLT.
MPSLP4: SOJLE T2,MPSLP1 ;IF CURRENT PAGE IS FINISHED, MAP THE NEXT PAGE
MPSLP5: SETZM .CPPSP##(P4) ;CLEAR FLAG THAT WE ARE IN SWEEP
PUSHJ P,CSDMP ;SWEEP THE CACHE TO FIX BAD PARITY IN MEMORY
JRST TPOPJ ;RESTORE T1 AND RETURN
> ;STILL IN FTMEMPAR CONDITIONAL
IFN FTMEMPAR!FTLOCK!FTMEMNXM,<
;SUBROUTINE - ABSOLUTE (ADDRESS TO) SEGMENT NUMBER
;CALL: MOVE P1,ABS.ADR(18 BIT FOR KA-10, 22 BIT FOR KI10)
; TLO P1,400000 ;IF VIRTUAL ADDRESS IS NOT REQUIRED
; PUSHJ P,@CP.ASN(P4)
; ERROR RETURN IF NOT IN MONITOR OR A HIGH OR LOW SEGMENT,
; OK RETURN J=0 IF IN MONITOR, OR HIGH OR LOW SEG, T1=REL. ADR
;CAN BE CALLED AT APR PI OR CLK PI(7). CANNOT BE CALLED AT UUO LEVEL
;NOTE: REL ADR. IS NOT VIRTUAL ADR ON HIGH SEGS
; SINCE THAT IS JOB DEPENDENT IF LOW SEG GR 400000
CPIASN::
CPLASN::SETZB T2,J ;ASSUME IN MONITOR (JOB 0 NOT A LEGAL JOB #)
LDB T1,[POINT 13,P1,26] ;SET REL. ADR. FROM ABS. ADR IN MONITOR
MOVE T1,PAGTAB(T1)
TLNE T1,MONTRB ;IS THIS A MONITOR PAGE?
JRST CPOPJ1## ;YES, GIVE OK RETURN WITH J=0
MOVE T3,P1 ;SET T3=ABSOLUTE ADDRESS OF ERROR WORD
LSH T3,W2PLSH## ;T3=ABSOLUTE PAGE NUMBER OF PAGE CONTAING BAD WORD
MOVEI T2,JOBMAX## ;SCAN TO SEE IF BAD ADDRESS IS IN A UPMP
AUPLOP: HRRZ T1,JBTUPM##(T2) ;T1=PAGE NUMBER OF THE UPMP
CAIE T1,(T3) ;BAD WORD IN THIS UPMP?
SOJG T2,AUPLOP ;NO, SCAN ALL USER PAGE MAP PAGES
JUMPG T2,CPOPJ1## ;JUMP IF THE PARITY ERROR WAS IN A UPMP
PUSHJ P,SSEUB
;LOOP - SCAN ALL HIGH AND LOW SEGS
ASNLOP: MOVEI T1,0 ;ASSUME PARITY ERROR IS IN PAGE 0 OF THIS SEGMENT
IFN FTVM,<
MOVSI T2,SHRSEG ;SHARABLE SEGMENT BIT
CAILE J,JOBMAX## ;A LOW SEGMENT?
TDNE T2,JBTSTS##(J) ;NO, IS IT SHARABLE
>
SKIPN JBTADR##(J) ;IS THIS JOB OR HIGH SEG IN CORE?
JRST ASNAOJ ;NO, LOOK AT THE NEXT SEGMENT
LDB T2,JBYHSA## ;ASSUME ITS A HIGH SEGMENT
; GET ITS STARTING PAGE NUMBER
CAILE J,JOBMAX## ;IS IT A HIGH SEGMENT?
JRST ASNHGH ;YES
PUSHJ P,STEUB ;NO, MAKE ITS FIRST PHYSICAL PAGE NUMBER ADDRESSABLE
; LOW SEGMENT ADDRESS IN THE UPMP IS
; VALID SINCE PARITY ERROR IS NOT IN A
; UPMP (VERIFIED ABOVE)
LDB T2,JBYLSA## ;STARTING PAGE NUMBER OF LOW SEGMENT
ASNHGH: CAIN T2,(T3) ;IS THIS PAGE THE SAME PAGE WHICH CONTAINED AN ERROR?
JRST ASNFND ;YES, COMPUTE THE RELATIVE ADDRESS OF THE
; WORD WITHIN THE SEGMENT WHICH CONTAINS THE ERROR
HRRZ T2,PAGTAB(T2) ;T2=PAGE NO. OF NEXT PAGE IN THIS SEGMENT
SKIPE T2 ;IS IT THE LAST PAGE IN THIS SEGMENT?
AOJA T1,ASNHGH ;NO, LOOK AT ALL THE PAGES IN THIS SEGMENT
ASNAOJ: CAIG J,JBTMAX## ;LOOKED AT ALL SEGMENTS?
AOJA J,ASNLOP ;NO, LOOK AT NEXT SEGMENT
POPJ P, ;NOT IN MONITOR OR ANY JOB
;HERE TO COMPUTE RELATIVE ADDRESS OF PARITY ERROR BY CONCATINATING RELATE
; PAGE NUMBER AND WORD NUMBER WITHIN THE PAGE
ASNFND: JUMPL P1,CPOPJ1## ;RETURN IF NOT INTERESTED IN VIRTUAL ADR
IFN FTVM,<
CAIG J,JOBMAX## ;A SHARABLE HIGH SEGMENT?
PUSHJ P,PHYPVP## ;NO, CONVERT FROM PHYSICAL TO VIRTUAL PAGE NUMBER
>
LSH T1,P2WLSH## ;MOVE PAGE NUMBER TO PAGE NUMBER FIELD
DPB P1,[POINT 9,T1,35]
; AND WORD NUMBER
JRST CPOPJ1## ;AND GIVE OKAY RETURN
> ;END IFN FTMEMPAR!FTLOCK!FTMEMNXM
IFN FTMEMNXM,<
;SUBROUTINE TO FIX CORE ALLOCATION TABLES AFTER NON-EXISTANT MEMORY
; IS ENCOUNTERED
;CALLING SEQUENCE:
; MAKE NXMTAB REFLECT CURRENT STATE OF MEMORY, GIVE BACK CORE
; BELONGING TO ALL SEGMENTS WHICH OVERLAP NXM, AND
; PUSHJ P,CPINXF ;FIX UP RELEVANT TABLES AND VARIABLES
;RETURNS CPOPJ IF NEW VALUE OF CORMAX .LE. OLD VALUE OF CORMAX (SOME
; JOB MAY BE TOO BIG TO SWAP IN), CPOPJ1 IF ALL IS OK.
CPINXF::
CPLNXF::PUSHJ P,SAVE2## ;SAVE WORKING ACS
SETZB T1,T2 ;INITIALIZE INDEXS INTO PAGTAB AND NXMTAB
MOVSI T3,400000 ;FIRST BIT TO LOOK AT IN NXMTAB
LDB T4,[POINT 14,MEMSIZ##,26]
MOVSI P1,NXMBIT ;LOOK FOR NON-EXISTANT PAGES
HRROI P2,MPGSIZ## ;DECREASE MAXMAX BY 1 PAGE FOR EACH NON-EXISTANT PAGE SEEN
CPINX1: TDNN P1,PAGTAB(T1) ;PAGE ALREADY MARKED AS NON-EXISTANT?
TDNN T3,NXMTAB##(T2) ;NO, IS IT NON-EXISTANT NOW?
JRST CPINX2 ;NO, FORGE AHEAD
SKIPL PAGTAB(T1) ;IS THIS NON-EXISTANT PAGE ON THE FREE CORE LIST?
STOPCD .,STOP,NPN, ;++NON-EXISTANT PAGE NOT FREE
ADDM P2,MAXMAX## ;DECREASE MAXMAX BY 1 PAGE
HLLM P1,PAGTAB(T1) ;AND MARK THIS PAGE AS NOW NON-EXISTANT
CPINX2: ADDI T1,1 ;NEXT PAGE
ROT T3,-1 ;NEXT BIT POSITION IN NXMTAB
SKIPG T3 ;CROSSED A WORD BOUNDARY?
ADDI T2,1 ;YES, BUMP TO NEXT WORD IN NXMTAB
SOJG T4,CPINX1 ;LOOP OVER ALL PAGES
CPINX3: MOVE T1,PAGPTR## ;POINTER TO THE FREE CORE LIST
JUMPE T1,CPINX5 ;JUMP IF THERE ARE CURRENTLY NO PAGES ON THE FREE LIST
TDNN P1,PAGTAB(T1) ;IS THIS PAGE NOW NON-EXISTANT?
JRST CPINX5 ;NO
MOVE T2,PAGTAB(T1) ;YES, LINK FREE CORE LIST AROUND THE PAGE
HRRZM T2,PAGPTR## ;STORE NEW FIRST PAGE ON THE FREE CORE LIST
SOS CORTAL## ;DECREMENT COUNT OF POTENTIALLY FREE PAGES
SOS BIGHOL## ;DECREMENT COUNT OF FREE PAGES
JRST CPINX3 ;CONTINUE TO LOOK AT PAGES AT THE BEGINNING
; OF THE FREE CORE LIST
CPINX4: MOVE T1,T2 ;CURRENT INDEX INTO PAGTAB
CPINX5: HRRZ T2,PAGTAB(T1) ;NEXT PAGE IN PAGTAB
JUMPE T2,CPINX6 ;JUMP IF THIS IS THE END OF THE FREE CORE LIST
TDNN P1,PAGTAB(T2) ;IS THIS PAGE NOW NON-EXISTANT?
JRST CPINX4 ;NO
HRRZ T2,PAGTAB(T2) ;YES, LINK THE FREE CORE LIST AROUND IT
HRRM T2,PAGTAB(T1) ; ..
SOS CORTAL## ;DECREMENT THE COUNT OF POTENTIALLY FREE PAGES
SOS BIGHOL## ;AND THE COUNT OF FREE PAGES
JRST CPINX5 ;LOOP OVER THE ENTIRE FREE CORE LIST
; STILL IN FTMEMNXM
CPINX6: MOVEI T1,0 ;INITIALIZE COUNT OF EXISTANT UNLOCKED PAGES
MOVE T2,MEMSIZ## ;PREVIOUS HIGHEST ADDRESS + 1
SUB T2,SYSSIZ## ;RANGE OF USERS CORE
LSH T2,W2PLSH## ;NUMBER OF PAGES FROM TOP OF THE MONITOR
; TO THE PREVIOUS TOP OF MEMORY
MOVE T3,SYSSIZ## ;WHERE TO START LOOKING FOR UNLOCKED EXISTANT PAGES
LSH T3,W2PLSH## ;PAGE NUMBER TO START AT
CPINX7: MOVE P1,PAGTAB(T3) ;PAGE DESCRIPTOR BITS FROM PAGTAB
TLNE P1,LKBITS-MONTRB;IS THIS PAGE LOCKED OR NON-EXISTANT?
JRST CPINX8 ;YES, DON'T CONSIDER IT IN COMPUTING NEW CORMAX
MOVEI T4,1(T3) ;HIGHEST EXISTANT PAGE + 1 THAT WAS SEEN
TLNN P1,MONTRB ;IS THIS A MONITOR PAGE?
ADDI T1,PAGSIZ## ;NO, INCREASE NEW CORMAX BY ONE PAGE
CPINX8: ADDI T3,1 ;NEXT PAGE IN PAGTAB
SOJG T2,CPINX7 ;LOOP OVER ALL PAGES
MOVEI T2,PAGTAB-1(T4) ;BYTE POINTER TO HIGHEST PAGE
HRRM T2,CORLST## ;STORE THAT FOR CHKTAL
LSH T4,P2WLSH## ;HIGHEST EXISTANT ADDRESS + 1
MOVEM T4,MEMSIZ## ;STORE THAT AS THE SIZE OF MEMORY
CAML T1,CORMAX## ;NEW CORMAX LESS THAN THE OLD CORMAX?
AOSA (P) ;NO, INDICATE ALL JOBS CAN STILL RUN
MOVEM T1,CORMAX## ;YES, STORE NEW VALUE OF CORMAX AND GIVE
; A NON-SKIP RETURN TO INDICATE THAT SOME
; JOBS MAY BE TO LARGE TO BE SWAPPED IN
POPJ P, ;RETURN
> ;END FTMEMNXM
IFN FTMONL,<
;HERE TO SET MEMORY ON LINE, T1 = FIRST PAGE TO SET ON LINE, T2 = LAST
; PAGE + 1
MEMONL::HRLZ S,T1 ;STARTING PAGE TO SET ON LINE
HRR S,T2 ;HIGHEST PAGE TO SET ON LINE
PUSH P,S ;SAVE THAT
SKIPN JBTADR##(J) ;DOES THIS JOB HAVE CORE?
PUSHJ P,GETMIN## ;NO, GET A MINIMUM AMOUNT FOR PDL, ETC.
JUMPE R,[POP P,(P) ;COULDN'T GET IT THIS TICK
JRST DLYCM##];GO AWAY AND TRY AGAIN NEXT TIME
POP P,S ;RESTORE RANGE OF ADDRESSES TO SET ON LINE
PUSHJ P,SAVCTX## ;SAVE THE JOB'S CONTEXT AND RETURN AT UUO LEVEL
; (THE JOB'S CONTEXT MUST BE SAVED BECAUSE
; IF SETTING THE MEMORY ON LINE CAUSES
; A NXM, THE JOB'S CONTEXT WILL BE DESTROYED)
HLRZ T1,S ;RESTORE THE STARTING PAGE TO SET ON LINE
HRRZ T2,S ;AND THE HIGHEST PAGE TO SET ON LINE
CAIG T2,1000 ;TRYING TO SET MEMORY ON LINE ABOVE 256K?
JRST MEMON5 ;NO, CAN DO THAT WITHOUT CHECKING
IFN FT22BIT,<;HERE IF SETTING MEMORY ON LINE ABOVE 256K TO SEE IF ANY CHANNEL IS IN
; 18 BIT MODE
HLRZ T3,SYSUNI## ;ADDRESS OF THE FIRST UDB IN THE SYSTEM
MEMON1: HRRZ T4,UNICHN##(T3) ;ADDRESS OF THE CHANNEL DATA BLOCK FOR THIS UNIT
SKIPL T4,CHB22B##(T4) ;IS THE CHANNEL IN 22 BIT MODE?
TLNE T4,CP.RH2 ;AN RH20?
CAIA ;YES
JRST MEMON4 ;NO, CAN ONLY SET UP TO 256K ON LINE
HLRZ T3,UNISYS##(T3) ;ADDRESS OF THE NEXT UNIT DATA BLOCK
JUMPN T3,MEMON1 ;JUMP IF NOT THE LAST
SKIPN T3,CNFMTA## ;ANY MAGTAPES?
JRST MEMON5 ;NO
MEMON2: HLRZ U,TDVUDB##(T3) ;ADDRESS OF THE UDB FOR THIS DDB
HRRZ T4,TDVKDB##(T3) ;ADDRESS OF THE CONTROLLER DB FOR THIS UNIT
HRRZ T4,TKBCDB##(T4) ;ADDRESS OF THE CHANNEL DB FOR THIS CONTROLLER
JUMPE T4,MEMON3 ;JUMP IF NOT A CHANNEL DEVICE
SKIPL CHB22B##(T4) ;IS IT IN 22 BIT MODE?
JRST MEMON4 ;NO, CAN ONLY SET UP TO 256K ON LINE
MEMON3: HLRZ T3,DEVSER(T3) ;ADDRESS OF THE NEXT DDB
JUMPE T3,MEMON5 ;ALL DONE IF THIS IS THE LAST DDB
MOVE T4,DEVMOD(T3) ;DEVICE CHARACTERISTICS
TLNE T4,DVMTA ;IS THIS A MTA DDB?
JRST MEMON2 ;YES, MAKE SURE ALL CHANNELS ARE IN 22 BIT MODE
JRST MEMON5 ;NO, ALL DONE
> ;END FT22BIT
MEMON4: MOVEI T2,1000 ;REDUCE THE HIGHEST PAGE TO SET ON LINE
; TO 256K SINCE SOME CHANNEL IS IN 18 BIT MODE
;STILL IN FTMONL
;HERE WHEN OPR IS REQUESTING .LE. 256K OR IF .GT. 256K, NO DF10 IN
; 18 BIT MODE WAS FOUND
MEMON5: MOVE T3,MEMSIZ## ;CURRENT HIGHEST ADDRESS IN THE MACHINE
MOVE T4,NWCORE## ;HIGHEST ADDRESS THAT CAN BE SET ON LINE
; (CANNOT MAKE PAGTAB AND MEMTAB BIGGER)
LSHC T3,W2PLSH## ;CONVERT TO PAGES
CAMG T3,T4 ;PICK THE BIGGER OF THE TWO AS THE
MOVE T3,T4 ; HIGHEST ADDRESS THAT CAN BE SET ON LINE
TRZE T3,PG.BDY## ;ROUND UP TO A 256K BOUNDARY (IF NOT
ADDI T3,PAGSIZ## ; ALREADY ON A 256K BOUNDARY
CAMG T3,T2 ;IF ASKING FOR MEMORY ON LINE ABOVE THE
; HIGHEST WHICH CAN BE DONE,
MOVE T2,T3 ; SET ON UP TO THE HIGHEST THAT CAN BE DONE
CAML T1,T2 ;LOWEST PAGE ABOVE THE HIGHEST PAGE?
POPJ P, ;YES, NOTHING TO SET ON LINE
MOVE P1,T1 ;LOWEST PAGE TO SET ON LINE
IDIVI P1,^D36 ;COMPUTE BIT POSITION AND WORD NUMBER WITHIN NXMTAB
MOVNI P2,-^D35(P2) ;BIT POSITION BYTE POINTER STYLE
HRLI P1,(POINT 1,0,0);FORM A 1 BIT BYTE POINTER TO NXMTAB
DPB P2,[POINT 6,P1,5]
ADDI P1,NXMTAB## ;BYTE POINTER TO BIT CORRESPONDING TO FIRST PAGE TO SET ON
MOVSI T3,NXMBIT ;BIT INDICATING NON-EXISTANT PAGE
SETZB T4,P2 ;INITIALIZE FIRST AND HIGHEST NON-EXISTANT PAGES SEEN
MOVEI P3,PAGSIZ## ;TO UPDATE MAXMAX ON EACH PAGE SET ON LINE
MEMON6: TDNN T3,PAGTAB(T1) ;IS THIS PAGE NON-EXISTANT?
JRST MEMON8 ;NO, ITS ALREADY ON LINE
ADDM P3,MAXMAX## ;INCREASE THE MAXIMUM VALUE FOR CORMAX
DPB T3,P1 ;INDICATE THAT THIS PAGE EXISTS IN NXMTAB
SKIPN P2 ;SKIP IF NOT THE FIRST PAGE SET ON LINE
MOVE P2,T1 ;REMEMBER THE FIRST PAGE SET ON LINE
JUMPE T4,MEMON7 ;JUMP IF FIRST PAGE
HRRZM T1,PAGTAB(T4) ;LINK PAGES BEING SET ON LINE TOGETHER
MEMON7: MOVE T4,T1 ;REMEMBER LAST PAGE
MEMON8: IBP P1 ;BUMP BYTE POINTER TO NEXT PAGE IN NXMTAB
CAIE T1,-1(T2) ;LOOKED AT THE ENTIRE RANGE OF PAGES TO SET ON LINE?
AOJA T1,MEMON6 ;NO, LOOK AT THE NEXT PAGE
JUMPE P2,CPOPJ## ;RETURN DOING NOTHING IF ALL PAGES WERE ALREADY
; ON LINE
SETZM PAGTAB(T4) ;INDICATE END OF THE LIST OF PAGES SET ON LINE
; STILL IN FTMONL
;HERE WHEN MEMORY HAS BEEN MARKED ON LINE TO ADD ALL PAGES WHICH
; WERE OFF LINE TO THE FREE CORE LIST
MOVE T1,P2 ;FIRST PAGE IN THE LIST OF PAGES SET ON LINE
MOVE P1,T4 ;LAST PAGE FREED
LSH T4,P2WLSH## ;HIGHEST ADDRESS SET ON LINE
ADDI T4,PAGSIZ## ;ADDRESS OF PAGE FOLLOWING HIGHEST SET ON LINE
CAMLE T4,MEMSIZ## ;IS THAT GREATER THAN CURRENT MEMORY SIZE?
MOVEM T4,MEMSIZ## ;YES, SAVE NEW HIGHEST ADDRESS IN MEMORY + 1
MOVE T4,MEMSIZ## ;HIGHEST ADDRESS IN MEMORY + 1
LSH T4,W2PLSH## ;CONVERT TO HIGHEST PAGE
MOVEI T4,PAGTAB-1(T4) ;BYTE POINTER TO HIGHEST PAGE IN MEMORY
HRRM T4,CORLST## ;STORE THAT FOR CHKTAL
PUSHJ P,GVPAGS ;ADD THE PAGES SET ON LINE TO THE FREE CORE LIST
;HERE TO REFERENCE PAGES ADDED TO THE FREE CORE LIST SO IF THEY ARE
; OFF LINE, IT WILL BE DETECTED BEFORE THEY ARE ATTEMPTED TO BE USED
MEMON9: HRRZ T1,P2 ;FIRST PAGE SET ON LINE
IDIVI T1,^D36 ;COMPUTE WORD AND BIT POSITION WITHIN NXMTAB
MOVE T2,BITTBL##(T2) ;MASK CORRESPONDING TO THAT BIT POSITION
TDNE T2,NXMTAB##(T1) ;IS THIS PAGE NOW ON LINE?
JRST MEMO11 ;NO, FORGET IT
HRRZ T3,P2 ;YES, GET PAGE NUMBER
TRO T3,PM.ACC+PM.WRT;ACCESS ALLOWED AND WRITEABLE
HRLM T3,.EPMP##+.MEUPM
CLRPGT (0,.EUPMP) ;FLUSH PAGE TABLE SO NEW MAPPING IS IN EFFECT
;WORRY ABOUT INTERLEAVED MEMORY
XP NXMDLY,PARDLY ;TIME TO WAIT FOR NXM FLAG TO COME UP
MOVEI T3,MEMITL## ;NUMBER OF WAYS MEMORY CAN BE INTERLEAVED
MOVEI T4,NXMDLY ;TIME TO WAIT FOR NXM FLAG TO CAUSE AN IRP.
MOVEM J,MOFLPG## ;FLAG THAT MEMORY BEING SET ON LINE
; NXM AT THIS POINT ISN'T A SERIOUS ERROR
MEMO10: SETZM .EUPMP-1(T3) ;REFRENCE THE PAGE TO MAKE SURE ITS REALLY THERE
SOJG T4,. ;WAIT LONG ENOUGH FOR NXM INTERRUPT TO HAPPEN
MOVEI T4,NXMDLY ; IN CASE IT ISN'T THERE
TDNN T2,NXMTAB##(T1) ;IS THE PAGE STILL ON LINE?
SOJG T3,MEMO10 ;YES, CHECK NEXT WORD OF THE PAGE
; TO INSURE THAT THERE ISN'T AN INTERLEAVING PROBLEM
SETZM MOFLPG## ;NO LONGER CHECKING FOR OFF LINE PAGES
MEMO11: CAIN P2,(P1) ;REFERENCED ALL PAGES IN THE RANGE SET ON LINE?
IFN FTDAEM,<
JRST [MOVE T1,[10,,.ERCSC]
PJRST DAEEIM##];YES, TELL DAEMON CONFIGURATION HAS CHANGED AND RETURN
>
IFE FTDAEM,<
POPJ P, ;IF NO DAEMON, JUST RETURN
>
HRRZ P2,PAGTAB(P2) ;NO, GET THE NEXT PAGE SET ON LINE
JRST MEMON9 ;AND REFERENCE IT TO MAKE SURE ITS THERE
> ;END FTMEMONL
SUBTTL CORE1 - CORE ALLOCATION MODULE
;ROUTINE TO ALLOCATE PHYSICAL CORE IN CORE OR ON THE DISK
;CALLING SEQUENCE:
; MOVE R,XWD PROTECTION,RELOCATION
; MOVE T1,HIGHEST RELATIVE ADDRESS REQUESTED
; PUSHJ P,CORE1A
;ALWAYS SKIP RETURN - R = NEW PROTECTION,,RELOCATION
; R = 0 IF CORE IS ASSIGNED ON THE SWAPPING SPACE
CORE1A::JUMPE R,CORGT0 ;JUMP IF SEGMENT HAS NO CORE IN CORE
HLRZ T3,R ;T3 = CURRENT HIGHEST RELATIVE ADDRESS IN THE SEGMENT
SKIPN T1 ;IS ZERO CORE BEING REQUESTED?
MOVNI T1,1 ;YES, PRETEND -1 AND DEPEND ON BUG IN ASH
; WHICH MAKES -1 = -1 WHEN SHIFTED
SUB T3,T1 ;T3 = NUMBER OF WORDS OF INCREASE OR DECREASE IN
; SEGMENT SIZE
ASH T3,W2PLSH## ;CONVERT TO NUMBER OF PAGES OF INCREASE OR DECREASE
JUMPG T3,CORE1B ;JUMP IF SEGMENT IS GETTING SMALLER
MOVMS T3 ;T3 = NUMBER OF PAGES OF INCREASE
PUSHJ P,FRDCR## ;ARE THERE THAT MANY FREE PAGES AVAILABLE IN CORE?
JRST CORGT7 ;NO, MARK THE SEGMENT AS EXPANDING AND ALLOCATE
; THE REQUIRED NUMBER OF PAGES ON SWAP-IN
PUSH P,T3 ;SAVE THE NUMBER OF PAGES OF INCREASE
PUSHJ P,SCPAGS ;FIND THE LAST PAGE WHICH IS CURRENTLY
; ALLOCATED TO THE SEGMENT
MOVE T2,(P) ;T2 = NUMBER OF PAGES TO ADD TO THE SEGMENT
IFN FTVM,<
ADDM T2,JBTSWP##(J) ;INCREASE IMGIN BY THAT NUMBER OF PAGES
>
PUSHJ P,ADPAGS ;ALLOCATE ENOUGH PAGES TO SATISFY THE REQUEST
POP P,T2 ;RESTORE THE NUMBER OF PAGES OF INCREASE
LSH T2,^D18+P2WLSH##;CONVERT TO NUMBER OF WORDS OF INCREASE IN
; POSITION TO UPDATE CURRENT RELOCATION
ADD R,T2 ;R = NEW PROTECTION,,RELOCATION
JRST CORGT2 ;STORE NEW PROTECTION,,RELOCATION AND CLEAR
; PAGES JUST ADDED TO INSURE SECURITY
CORE1B: JUMPG T1,CORE1C ;REQUESTING 0K CORE IN CORE?
IFN FTMS,<
PUSHJ P,CLCSN## ;YES, DON'T HAVE TO SWEEP BEFORE WE
; RUN HIM AGAIN
>;END IFN FTMS
PUSHJ P,SVEUB ;YES, MAY BE FROM THE SWAPPER AND THE UPMP
; IS NOT NECESSARILY ADDRESSABLE SO MAKE SURE IT IS
PUSH P,T3 ;SAVE THE NUMBER OF PAGES OF DECREASE
MOVEI T2,0 ;FIND THE FIRST PAGE OF THE SEGMENT
PUSHJ P,SNPAGS ;T1 = FIRST PAGE TO RETURN TO FREE CORE LIST
JRST CORE1D ;GO RETURN PAGES
CORE1C: LDB T2,[POINT 9,R,8];T2 = THE CURRENT SIZE OF THE SEGMENT IN
; PAGES - 1
SUBI T2,(T3) ;COMPUTE THE RELATIVE PAGE NUMBER OF THE FIRST
; PAGE TO RETURN TO THE FREE CORE LIST
PUSH P,T3 ;SAVE THE NUMBER OF PAGES OF DECREASE
PUSHJ P,SNPAGS ;FIND THE ABSOLUTE PAGE NUMBER OF THE FIRST PAGE
; TO RETURN TO THE FREE CORE LIST
HRRZ T2,PAGTAB(T1) ;T2 = THE LINK TO THE FIRST PAGE TO FREE
HLLZS PAGTAB(T1) ;INDICATE THAT THIS IS NOW THE LAST PAGE
; OF THE SEGMENT
MOVE T1,T2 ;T1 = THE ABSOLUTE PAGE NUMBER OF FIRST PAGE TO FREE
CORE1D: PUSHJ P,GVPAGS ;RETURN FREED PAGES TO THE FREE CORE LIST
IFN FTVM,<
LDB T2,IMGOUT## ;SWAPPER DEALLOCATION?
JUMPN T2,CORE1E ;JUMP IF YES
MOVN T2,(P) ;NUMBER OF PAGES BEING DEALLOCATED
ADDM T2,JBTSWP##(J) ;UPDATE IMGIN TO REFLECT NUMBER OF PAGES ALLOCATED
CORE1E:>
POP P,T2 ;RESTORE THE NUMBER OF PAGES OF DECREASE
LSH T2,^D18+P2WLSH##;CONVERT TO NUMBER OF WORDS OF DECREASE AND
; POSITION TO UPDATE CURRENT RELOCATION
SUB R,T2 ;R = NEW PROTECTION,,RELOCATION
SKIPG R ;WERE ALL OF THE PAGES BELONGING TO THE SEGMENT
; RETURNED TO FREE CORE
SETZB T1,R ;YES, INDICATE SEGMENT HAS NO CORE IN CORE
CAILE J,JOBMAX## ;IS THIS SEGMENT A HIGH SEGMENT?
JUMPE R,CORGT1 ;YES, AND DOES IT STILL HAVE CORE IN CORE?
JUMPN R,CORGT2 ;NO, DOES LOW SEGMENT HAVE CORE IN CORE?
HRRZ T1,JBTUPM##(J) ;NO, RETURN UPMP TO THE FREE CORE LIST
SETZ R,
HLLZS JBTUPM##(J) ;INDICATE NO UPMP OR CORE IN CORE
PUSHJ P,GVPAGS ;GIVE UP THE PAGE ALLOCATED TO THE UPMP
JRST CORGT6 ;STORE R AND RETURN
;HERE WHEN THE SEGMENT IS EXPANDING FROM ZERO (CALLED BY THE SWAPPER AND ABOVE)
CORGET::PUSHJ P,SVEUB ;SAVE UBR ON CALL FROM THE SWAPPER
CORGT0: JUMPE T1,CPOPJ1## ;RETURN IF MULTIPLE CALLS TO RETURN CORE
AOS T2,T1 ;T2 = NUMBER OF WORDS OF CORE REQUIRED TO
; SATISFY REQUEST
LSH T2,W2PLSH## ;T2 = NUMBER OF PAGES REQUIRED
CAIG J,JOBMAX## ;IS THIS A LOW SEGMENT?
CAMGE T2,BIGHOL## ;YES, MUST ALLOCATE A UPMP ALSO
CAMLE T2,BIGHOL## ;NO, IS THERE ENOUGH FREE CORE IN CORE TO
; ACCOMODATE THE REQUEST?
SOJA T1,CORGT7 ;NO, MARK THE SEGMENT AS EXPANDING AND ALLOCATE
; THE REQUIRED NUMBER OF PAGES ON SWAP-IN
IFN FTVM,<
DPB T2,IMGIN## ;STORE THE NUMBER OF PAGES ALLOCATED IN CORE
>
HRLI R,-1(T1) ;R = NEW PROTECTION,,?
PUSHJ P,GTPAGS ;ALLOCATE THE PAGES TO SATIFY THE REQUEST
MOVEI T1,PM.ACC+PM.WRT(T1)
CAILE J,JOBMAX## ;IS THIS A LOW SEGMENT
JRST CORGT1 ;NO, UPMP HAS ALREADY BEEN ALLOCATED
PUSH P,T1 ;SAVE THE PAGE NUMBER OF FIRST PAGE OF THE LOW SEGMENT
MOVEI T2,1 ;ALLOCATE ONE PAGE FOR THE UPMP
PUSHJ P,GTPAGS ;GET ONE PAGE OFF THE FREE CORE LIST
HRRM T1,JBTUPM##(J) ;STORE IT AS THE ADDRESS OF THE UPMP
MOVEI T1,PM.ACC+PM.WRT+PM.CSH(T1)
;(CACHE UPMP)
HRLM T1,.EPMP##+.MEUPM
CLRPGT (0,.EUPMP)
SETZM .EUPMP
MOVE T2,[.EUPMP,,.EUPMP+1]
BLT T2,.EUPMP+PG.BDY## ;ZERO THE ENTIRE UPMP
MOVSI T2,NLUPMP##+.MUPMP ;NOW SETUP THE REST OF THE MAP FROM THE
HRRI T2,.EUPMP+.MUPMP ; PROTOTYPE MAP (NULL JOB'S UPMP)
BLT T2,.EUPMP+NUPMPL##-1
HRLM T1,.EUPMP+.MUPMP;MAP THE UPMP IN THE PER-PROCESS MAP
POP P,T1 ;RESTORE THE MAPPING FOR THE FIRST PAGE OF THE
; LOW SEGMENT
PUSHJ P,STEUB ;MAKE THE UPMP ADDRESSABLE (SET THE UBR TO
; PONIT TO THIS PAGE)
HRLM T1,.UPMP ;STORE THE MAPPING FOR THE FIRST PAGE OF
; THE LOW SEGMENT
HRRM T1,.UPMP+.MJDAT ;AND MAKE THE JOB DATA AREA ADDRESSABLE THROUGH
; THE PER PROCESS MAP
BLKO PAG,.JDAT ;CLEAR OUT OLD ENTRY FOR .JDAT
JRST CORGT2 ;CLEAR THE PAGES JUST ALLOCATED
CORGT1: DPB T1,JBYHSA## ;STORE THE STARTING PAGE NUMBER OF THE HIGH SEGMENT
CORGT2: JUMPE R,CORGT6 ;ALL DONE IF THE SEGMENT HAS NO CORE AT THIS POINT
HLRZ T1,R ;T1 = HIGHEST RELATIVE ADDRESS SEGMENT CURRENTLY HAS
HLRZ T2,JBTADR##(J) ;T2 = HIGHEST RELATIVE ADDRESS SEGMENT PREVIOUSLY HAD
JUMPN T2,CORGT3 ;JUMP IF SEGMENT HAD CORE IN CORE
LDB T2,IMGOUT## ;T2 = AMOUNT OF CORE SEGMENT HAD WHEN LAST IN CORE
LSH T2,P2WLSH## ;CONVERT TO NUMBER OF WORDS
SOS T2 ;HIGHEST RELATIVE ADDRESS
CORGT3: CAMG T1,T2 ;CURRENT SEGMENT SIZE GREATER THAN PREVIOUS SIZE?
JRST CORGT5 ;NO, NOTHING TO CLEAR
SUB T1,T2 ;T1 = NUMBER OF WORDS OF INCREASE
ADDI T2,1 ;T2 = NUMBER OF WORDS PREVIOUSLY ALLOCATED THE SEGMENT
LSH T2,W2PLSH## ;CONVERT TO PAGE NUMBER OF LAST PAGE
; PREVIOUSLY ALLOCATED TO THE SEGMENT
IFN FTVM,<
PUSHJ P,ZERHGH## ;IF JOB HAS A NON-SHARABLE HI-SEG
JRST CORGT5 ; ZERO THE CORE DIFFERENTLY
>
IFN FTTIME,<
ADDM T1,CLRWRD## ;INCREASE COUNT OF NUMBER OF WORDS CLEARED
>
PUSHJ P,SNPAGS ;GET THE ABSOLUTE PAGE NUMBER OF THE FIRST
; NEW PAGE (PAGE TO BE CLEARED)
CORGT4: MOVEI T1,PM.ACC+PM.WRT+PM.CSH(T1)
HRLM T1,.EPMP##+.MEUPM
CLRPGT (0,.EUPMP)
MOVEI T2,.EUPMP+1 ;MAKE A BLT POINTER
HRLI T2,.EUPMP ;SET TO ZERO THE PAGE
SETZM .EUPMP ;ZERO THE FIRST WORD OF THE PAGE
BLT T2,.EUPMP+PAGSIZ##-1
;ZERO THE PAGE
TRZ T1,PM.ACC+PM.WRT+PM.CSH ;CLEAR THE ACCESS BITS
HRRZ T1,PAGTAB(T1) ;GET THE ABSOLUTE PAGE NUMBER OF THE
; NEXT PAGE OF THE SEGMENT
JUMPN T1,CORGT4 ;IF NOT THE LAST PAGE ZERO IT
CORGT5: HRRI R,.VJDT ;ASSUME A HIGH SEGMENT,.I.E., RH(R) = EVA
; OF THE VESTIGUAL JOB DATA AREA
CAILE J,JOBMAX## ;IS IT A HIGH SEGMENT?
JRST CORGT6 ;NO
HRRI R,.JDAT ;LOW SEGMENT, RH(R) = EVA OF JOB DATA AREA
IFN FTVM,<
MOVEM J,.UPMP+.UPJOB ;SAVE THE JOB NUMBER FOR DEBUGGING AND
; VIRCHK (FOR GIVING BACK HIGH SEG CORE)
>
HLRZM R,JOBREL##(R) ;STORE THE NEW SIZE OF THE LOW SEGMENT FOR THE
; USER SO HE WON'T GET CONFUSED ON EXAMINE COMMAND
CORGT6: SKIPE R ;GETTING CORE?
PUSHJ P,IICLNK## ;YES
SKIPN R ;GIVING UP CORE?
PUSHJ P,DICLNK## ;YES
MOVEM R,JBTADR##(J) ;STORE NEW PROTECTION,,RELOCATION
IFN FTTRACK,<
MOVEM J,LASCOR## ;STORE SEGMENT NUMBER OF LAST SEGMENT CORE
; ALLOCATION WAS DONE FOR FOR DEBUGGING
>
IFN FTVM,<
LDB T1,IMGOUT## ;CORE ALLOCATION FOR THE SWAPPER?
JUMPN T1,CPOPJ1## ;YES, ALL DONE
>
CAMN J,.C0JOB## ;IS THIS THE CURRENT JOB (CORE UUO)?
PUSHJ P,SETREL ;YES, SETUP THE MAP AND SOFTWARE RELOCTATION INFO.
AOS (P) ;GIVE SKIP (OK) RETURN
CAILE J,JOBMAX## ;IS THIS A HIGH SEGMENT?
PJRST CURHGH## ;YES SEE IF CORE WAS ALLOCATED FOR THE HIGH
; SEGMENT WHICH THE CURRENT JOB MIGHT BE SHARING
IFE FTVM,<
CAME J,.C0JOB## ;IS THIS THE CURRENT JOB?
>
IFN FTVM,<
CAMN J,.C0JOB## ;CURRENT JOB?
TLNN R,MPGSIZ## ; OR ONLY ONE PAGE ALLOCATED TO THE CURRENT JOB?
; IF ONLY 1 PAGE SETREL MIGHT NOT CALL MAPLOW
>
PJRST MAPLOW ;NO, SETUP THE MAP FOR E AND D COMMANDS
POPJ P, ;YES, MAP IS ALREADY SETUP
;HERE IF NOT ENOUGH FREE PAGES AVAILABLE IN CORE TO SATISFY REQUEST
; INDICATE JOB IS EXPANDING AND THE REQUIRED NUMBER OF PAGES WILL BE
; ALLOCATED WHEN THE SEGMENT IS NEXT SWAPPED IN
CORGT7:
AOS (P) ;SET FOR SKIP RETURN
PJRST XPAND## ;AND MARK THE JOB AS EXPANDING
;ROUTINE TO SETUP THE PORTION OF THE MAP WHICH MAPS THE
; LOW SEGMENT
;CALLING SEQUENCE:
; MOVE R,LOW SEGMENT PROTECTION,,RELOCATION
; PUSHJ P,MAPLOW
; ... ALWAYS RETURN HERE
MAPLOW::
IFN FTVM,<
LDB T1,JBYLSS## ;HIGHEST PAGE IN THE LOW SEGMENT
ADDI T1,1 ;LOW SEGMENT SIZE
PUSHJ P,CLRWS## ;CLEAR WORKING SET BITS
LDB T1,[POINT 9,R,8];NEW HIGHEST PAGE IN THE LOW SEGMENT
ADDI T1,1 ;NEW LOW SEGMENT SIZE
PUSHJ P,ADJWS## ;SET WORKING SET BITS FOR NEW SIZE
> ;END FTVM
MOVE T1,[POINT 18,.UPMP] ;START AT PAGE ZERO
MOVEI T2,PM.ACC+PM.WRT+PM.PUB+PM.CSH ;ACCESSABLE, WRITABLE, PUBLIC, AND CACHE
IFN FTLOCK,<
MOVSI T3,(JS.NCS) ;DON'T CACHE BIT
TDNE T3,JBTST2##(J) ;SHOULD CACHE BIT BE OFF IN THE MAP?
PUSHJ P,[TRZ T2,PM.CSH ;YES, CLEAR IT
PJRST CSDMP] ;AND FLUSH THE CACHE
>
LDB T3,JBYLSA## ;FIRST PHYSICAL PAGE IN THE LOW SEGMENT
PUSHJ P,REMAP ;SETUP THE MAP FOR THE LOW SEGMENT
LDB T3,JBYLSS## ;PREVIOUS SIZE
PUSHJ P,ZERMAP ;CLEAR MAP SLOTS NO LONGER A PART OF THE LOW SEGMENT
DPB T2,JBYLSS## ;STORE NEW LOW SEGMENT SIZE
pjrst steub ;clear page table and return
;ROUTINE TO SETUP THE PORTION OF THE MAP WHICH MAPS THE HIGH SEGMENT
;CALLING SEQUENCE:
; PUSHJ P,MAPHGH
; ... ALWAYS RETURN HERE - R = PROTECTION,,RELOCATION OF LOW SEGMENT
SETMAP::SKIPA J,.C0JOB## ;CURRENT JOB NUMBER
REMHGH::TDZA T3,T3 ;NO HIGH SEGMENT NUMBER
MAPHGH::MOVE T3,JBTSGN##(J) ;HIGH SEGMENT NUMBER
PUSHJ P,SVEUB ;MAKE SURE THE JOB IS ADDRESSABLE
PUSHJ P,HSVAD## ;COMPUTE HIGH SEGMENT STARTING AND ENDING ADDRESSES
MOVE T4,T2 ;STARTING ADDRESS
SKIPL R,T3 ;SPY SEGMENT?
HLRZ R,JBTADR##(T3) ;NO, SIZE OF THE REAL HIGH SEGMENT
HRLZS R ;HIGH SEGMENT SIZE,,0
SKIPL JOBHCU##+.JDAT ;SAVE IN PROGRESS?
HRRM T1,JOBHRL##+.JDAT ;YES, DON'T CLOBBER IOWD IN COMPRESSED LOW SEGMENT
IFN FTVM,<
TLNN T3,SHRSEG+SPYSEG ;SHARABLE SEGMENT?
JUMPN T3,SCWEXO## ;YES, THE MAP IS RIGHT EXCEPT FOR W.E. AND PUBLIC BITS
>
ROT T4,W2PLSH##-1 ;CONVERT STARTING ADDRESS TO PAGE NUMBER/2
MOVEI T1,.UPMP(T4) ;WORD IN THE UPMP WHERE HIGH SEGMENT MAPPING STARTS
HRLI T1,442200 ;ASSUME HIGH SEGMENT STARTS AT AN EVEN PAGE NUMBER
SKIPGE T4 ;DOES IT?
HRLI T1,222200 ;NO, IT STARTS AT AN ODD PAGE NUMBER
MOVEI T2,PM.ACC+PM.WRT+PM.CSH ;ACCESS ALLOWED, WRITABLE AND CACHE
IFN FTLOCK!FTMS,<
TLNE T3,NCSH+NOCSH ;CACHE?
PUSHJ P,[TRZ T2,PM.CSH ;NO, CLEAR THE BIT
PJRST CSDMP] ;AND FLUSH THE CACHE
>
TLNN T3,GTSSEG ;SEGMENT GETSEGED?
JRST SETM0A ;NO, ALWAYS PUBLIC
IFN FTFDAE,<
MOVSI T4,(JS.FXO) ;FILE DAEMON MADE IT EXECUTE ONLY BIT
TDNE T4,JBTST2##(J) ;IS IT EXECUTE ONLY?
JRST SETM0B ;YES, LEAVE IT CONCEALED
>
MOVE T4,JBTSTS##(J) ;JOB STATUS
TRNE T4,JS.XO ;EXECUTE ONLY?
TLNE T4,JACCT ;IF ALSO JACCT, FORGET ABOUT X.O.
SETM0A: TRO T2,PM.PUB ;JACCT OR NOT EXECUTE ONLY, SO MAKE PAGES PUBLIC
SETM0B: TLNN T3,UWPOFF ;USER WRITE PROTECT OFF?
TRZ T2,PM.WRT ;YES, MAKE THE SEGMENT WRITABLE
JUMPL T3,SETMP1 ;JUMP IF A SPY SEGMENT
LDB T3,[POINT 13,JBTHSA##(T3),35] ;FIRST PHYSICAL PAGE OF THE HIGH SEGMENT
MOVEI T4,PM.ACC+PM.WRT(T3) ;ACCESS ALLOWED PLUS WRITABLE
HRLM T4,.UPMP+.MVJDT ;MAKE THE HIGH SEGMENT VESTIGUAL JOB DATA AREA
; ADDRESSABLE VIA THE PER-PROCESS MAP
PUSHJ P,REMAP ;MAP THE HIGH SEGMENT INTO THE USER'S ADDRESS SPACE
JRST SETMP3 ;CONTINUE
SETMP1: TRZ T2,PM.CSH ;DON'T ALLOW USERS TO GET THINGS
;INTO THE CACHE THAT SHOULN'T BE THERE
LDB T3,[POINT 9,R,8];SIZE OF THE SPY SEGMENT
TRO T2,PM.PUB ;EXECUTE ONLY SPY SEG DOESN'T WORK
SETMP2: IDPB T2,T1 ;MAP MONITOR ADDRESSES INTO USER'S ADDRESS SPACE
AOS T2 ;STEP TO NEXT MONITOR PAGE
SOJGE T3,SETMP2 ;MAP AS MANY PAGES AS THE USER REQUESTED
SETMP3: LDB T3,JBYHSS## ;PREVIOUS HIGH SEGMENT SIZE
TLNE R,-1 ;IF THE HIGH SEGMENT SIZE ISN'T 0,
SUBI T3,1 ;HIGHEST PAGE IN THE HIGH SEGMENT
PUSHJ P,ZERMAP ;ZERO MAP SLOTS NO LONGER A PART OF THE HIGH SEGMENT
TLNE R,-1 ;IF THERE STILL IS A HIGH SEGMENT
ADDI T2,1 ;COMPUTE NEW NUMBER OF PAGES IN THE HIGH SEGMENT
DPB T2,JBYHSS## ;STORE NEW NUMBER OF PAGES IN THE HIGH SEGMENT
MOVE R,JBTADR##(J) ;LOW SEGMENT SIZE,,VIRTUAL ADDRESS
POPJ P, ;AND RETURN TO THE CALLER
;SUBROUTINE TO SETUP THE USER PAGE MAP PAGE TO REFLECT THE LOCATION
; OF THE PAGES OF A SEGMENT IN PHYSICAL MEMORY
;CALLING SEQUENCE:
; MOVE T1,BYTE POINTER TO THE MAP
; MOVE T2,PAGE ATTRIBUTES
; MOVE T3,ABSOLUTE PAGE NUMBER OF FIRST PAGE OF THE SEGMENT
; PUSHJ P,REMAP
; ... ALWAYS RETURN HERE
REMAP: HLRZ T4,R ;LENGTH - 1 OF THE SEGMENT
JUMPE T4,CPOPJ## ;IF THE SEGMENT IS ZERO LENGTH RETURN
LSH T4,W2PLSH## ;CONVERT TO NUMBER OF PAGES - 1
REMAP1: TRO T3,(T2) ;ABSOLUTE PAGE NUMBER PLUS ACCESS BITS
IDPB T3,T1 ;STORE PHYSICAL LOCATION OF THE PAGE AND
; THE ACCESS BITS IN THE MAP
TRZ T3,(T2) ;CLEAR ACCESS BITS
MOVE T3,PAGTAB(T3) ;GET THE ABSOLUTE PAGE NUMBER OF THE NEXT
; PAGE IN THE SEGMENT
SOJL T4,CPOPJ## ;RETURN IF ALL THE PAGES IN THE SEGMENT
; HAVE BEEN MAPPED
JUMPG T3,REMAP1 ;MAP ALL THE PAGES IN THE SEGMENT
STOPCD .,STOP,PMU, ;++PAGTAB MESSED UP
;ROUTINE TO DETERMINE IF THE SIZE OF A SEGMENT HAS CHANGED SINCE THE LAST
; TIME THE JOB WHOSE ADDRESSING SPACE CONTAINS THIS SEGMENT WAS RUN. IF THE
; SEGMENT IS SMALLER THAN THE IT PREVIOUSLY WAS, THE ROUTINE
; ZEROES THE LOCATIONS IN THE MAP WHICH CORRESPOND TO THE PAGES REMOVED FROM
; THE SEGMENT (OR ALL THE LOCATIONS IF THE SEGMENT WAS REMOVED) SO THE JOB
; WILL PAGE FAIL ON AN ILLEGAL MEMORY REFERENCE
;CALLING SEQUENCE:
; MOVE T3,PREVIOUS SEGMENT SIZE IN PAGES - 1
; MOVE R,JBTADR##(J)
; PUSHJ P,ZERMAP
; ... ALWAYS RETURN HERE - T2 = CURRENT SEGMENT SIZE IN PAGES - 1
ZERMAP: LDB T2,[POINT 9,R,8];CURRENT SIZE OF THE SEGMENT - 1 IN PAGES
SUBI T3,(T2) ;NEW SIZE MINUS OLD SIZE
JUMPLE T3,CPOPJ## ;RETURN IF THE SEGMENT IS THE SAME
; SIZE OR BIGGER THAN IT WAS THE LAST TIME
; THE JOB WAS RUN
MOVEI T4,0 ;ZERO THE MAP TO REFLECT THE NEW SMALLER
ZRMAP1: IDPB T4,T1 ; SEGMENT SIZE SO JOB WILL PAGE FAIL ON AN
SOJG T3,ZRMAP1 ; ILLEGAL MEMORY REFERENCE
POPJ P, ;RETURN
;SUBROUTINE TO RETURN PAGES TO THE LINKED LIST OF FREE PAGES AND UPDATE
; BIGHOL (THE TOTAL NUMBER OF FREE PAGES) AND CORTAL (THE TOTAL NUMBER
; OF FREE PAGES PLUS THE NUMBER OF PAGES OCCUPIED BY
; DORMANT OR IDLE SEGMENTS)
;CALLING SEQUENCE:
; MOVE T1,FIRST PAGE TO RETURN TO THE FREE CORE LIST
; PUSHJ P,GVPAGS
; ALWAYS RETURN HERE
GVPAGS::HRRZS T2,T1 ;T2 = FIRST PAGE TO RETURN (CLEAR ANY JUNK IN LH)
EXCH T1,PAGPTR## ;STORE FIRST PAGE TO FREE AS FIRST PAGE ON THE
; FREE CORE LIST AND GET FIRST PAGE ON CURRENT LIST
MOVEI T3,1 ;AT LEAST ONE PAGE IS BEING RETURNED
GVPAG1: MOVSI T4,FREPAG ;THIS PAGE IS ON THE FREE CORE LIST BIT
TDNE T4,PAGTAB(T2) ;PAGE MUST NOT BE FREE ALREADY
STOPCD .,STOP,ARF, ;++ATTEMPT TO RETURN FREE PAGE
IORB T4,PAGTAB(T2) ;MARK THIS PAGE AS BEING ON THE FREE CORE LIST
; AND GET THE NEXT PAGE TO BE RETURNED
TRNN T4,-1 ;LAST PAGE TO BE RETURNED?
JRST GVPAG2 ;YES, UPDATE BIGHOL AND CORTAL AND RETURN
HRRZ T2,T4 ;INDEX TO NEXT PAGE TO FREE
AOJA T3,GVPAG1 ;COUNT NUMBER OF PAGES FREED AND RETURN NEXT PAGE
GVPAG2: HRRM T1,PAGTAB(T2) ;LINK THE REST OF THE FREE CORE LIST TO THE PAGES
; FREED
ADDM T3,BIGHOL## ;UPDATE THE AMOUNT OF FREE CORE BY THE NUMBER
; OF PAGES FREED
ADDM T3,CORTAL## ;ALSO, UPDATE THE AMOUNT OF POTENTIALLY FREE CORE
POPJ P, ;AND RETURN
;SUBROUTINE TO FIND THE NTH PAGE FOR N.LT.THE NUMBER OF PAGES
; ASSIGNED TO THE JOB OR THE JOBS LAST PAGE
;CALLING SEQUENCE:
; PUSHJ P,SCPAGS ;TO FIND THE LAST PAGE OF THE JOB
;OR
; PUSHJ P,SNPAGS ;TO FIND THE NTH PAGE OF A JOB
; RETURN HERE - T1 = PAGE NUMBER OF THE NTH PAGE
SCPAGS::MOVEI T2,^D511 ;STOP AFTER SCANNING 512 PAGES
SNPAGS::LDB T3,JBYHSA## ;PHYSICAL PAGE NUMBER OF PAGE 0 IN THE LOW SEGMENT
CAIG J,JOBMAX## ;IS THIS A HIGH SEGMENT?
LDB T3,JBYLSA## ;YES, PHYSICAL PAGE NUMBER OF FIRST PAGE OF
; THE HIGH SEGMENT
SNPAG1: HRRZ T1,T3 ;CURRENT PAGE WITHIN THE SEGMENT
SKIPGE T3,PAGTAB(T1) ;GET NEXT PAGE IN THE SEGMENT
STOPCD .,STOP,PSF, ;++PAGE IN SEGMENT FREE
TRNE T3,-1 ;IS THIS THE LAST PAGE IN THE SEGMENT?
SOJGE T2,SNPAG1 ;NO, IS THIS THE NTH PAGE WITHIN THE SEGMENT?
POPJ P, ;YES, RETURN WITH T1 = NTH OR LAST PAGE
;SUBROUTINE TO GET PAGES FROM THE LINKED LIST OF FREE PAGES AND
; UPDATE CORTAL AND BIGHOL
;CALLING SEQUENCE:
; MOVE T1,WHERE TO BEGIN ALLOCATION IF ADDING PAGES
; MOVE T2,NUMBER OF PAGES TO ALLOCATE
; PUSHJ P,ADPAGS ;OR
; PUSHJ P,GTPAGS ;IF NO PAGES ARE CURRENTLY ALLOCATED
; ALWAYS RETURN HERE - T1 = PAGE NUMBER OF FIRST PAGE ALLOCATED
ADPAGS::MOVE T4,PAGPTR## ;FIRST FREE PAGE
HRRM T4,PAGTAB(T1) ;LINK IT TO THE PAGES CONTAINED IN THIS SEGMENT
GTPAGS: SKIPN T1,PAGPTR## ;GET FIRST FREE PAGE
STOPCD .,STOP,PEZ, ;++PAGPTR=0
MOVNS T2 ;MINUS NUMBER OF PAGES BEING ALLOCATED
ADDM T2,BIGHOL## ;DECREASE THE NUMBER OF FREE PAGES BY THAT AMOUNT
ADDM T2,CORTAL## ;AND THE NUMBER OF POTENTIALLY FREE PAGES
MOVE T3,T1 ;FIRST PAGE TO ADD OR GET
GTPAG1: HRRZ T4,T3 ;ALLOCATE THIS PAGE
MOVSI T3,FREPAG ;PREPARE TO MARK THIS PAGE AS IN-USE
SKIPN T4 ;END OF THE FREE CORE LIST?
STOPCD .,STOP,FPI, ;++FREE PAGE INUSE
ANDCAB T3,PAGTAB(T4) ;CLEAR THE BIT INDICATING A FREE PAGE AND GET
; THE NEXT PAGE ON THE FREE CORE LIST
AOJL T2,GTPAG1 ;LOOP UNTIL ALL PAGES REQUESTED ARE ALLOCATED
HRRZM T3,PAGPTR## ;STORE THE NEW FIRST PAGE IN THE FREE CORE LIST
HLLZS PAGTAB(T4) ;INDICATE THAT THIS IS THE LAST PAGE ALLOCATED
; TO THIS SEGMENT
POPJ P, ;AND RETURN TO THE CALLER
SUBTTL SWAP - USER PROGRAM SWAPPING ROUTINES
;SUBROUTINE TO SETUP THE MAP FOR A JOB WHICH WAS JUST SWAPPED IN
; THIS INCLUDES THE TRAP LOCATIONS AS WELL AS THE MAP ITSELF
;CALLING SEQUENCE:
; MOVE J,JOB NUMBER OF JOB JUST SWAPPED IN
; MOVE R,XWD LOW SEGMENT SIZE, EVA OF THE JOB DATA AREA
; SETUP THE USER BASE REGISTER TO POINT TO THIS JOB'S UPMP
; PUSHJ P,MAPUSR
; ALWAYS RETURN HERE
MAPUSR::PUSHJ P,SVEUB ;MAKE THE MAP ADDRESSABLE
MOVE R,JBTADR##(J) ;R=WXD LOW SEGMENT SIZE, ADDRESS OF JOB DATA AREA
MOVE T1,JOBPC##(R) ;JOBS PC
TLNN T1,(XC.USR) ;JOB IN EXEC MODE?
MOVEM R,JOBDPG##(R) ;YES, STORE POSSIBLY UPDATED R IN THE DUMP ACS
IFE FTVM,<
PUSHJ P,MAPLOW ;MAP THE LOW SEGMENT
>
PUSHJ P,MAPHGH ;MAP THE HIGH SEGMENT
MOVE T1,JOBENB##(R) ;GET THE JOBS ENABLE BITS
PJRST SETRP ;SETUP THE TRAP LOCATIONS
SUBTTL SWPSER - SWAPPING SERVICE ROUTINE
;SUBROUTINE TO MAKE THE FIRST WORD OF A SEGMENT ADDRESSABLE FOR JBTCHK
; CALLING SEQUENCE:
; MOVE T1,IOWD USED FOR SWAPPING
; MOVE J,SEGMENT NUMBER OF SEGMENT SWAPPED IN OR OUT
; PUSHJ P,GETCHK
; ALWAYS RETURN HERE
;T1 = EXEC VIRTUAL ADDRESS OF WORD 0 OF THE SEGMENT. IF THIS IS A LOW
; SEGMENT, JUST SETUP THE UBR SINCE T1 CONTAINS THE ADDRESS OF WORD 0
; OF THE SEGMENT MAPPED THROUGH THE PER PROCESS MAP. IF THIS IS A HIGH
; SEGMENT, MAP WORD 0 THROUGH THE EXEC MAP SINCE THE SEGMENT MAY BE
; DORMANT OR IDLE AND THUS NOT APPEAR IN ANY USERS MAP.
GETCHK::CAIG J,JOBMAX## ;IS THIS A HIGH SEGMENT?
JRST SVEUB ;NO, JUST SETUP THE UBR SINCE THE LOW SEGMENT
; IS ADDRESSABLE VIA THE PER PROCESS MAP
LDB T1,JBYHSA## ;GET THE ABSOLUTE PAGE NUMBER OF THE FIRST
; PAGE OF THE HIGH SEGMENT
TRO T1,PM.ACC+PM.WRT;SET ACCESS BITS
HRRM T1,.EPMP##+.MECKS
;MAP WORD 0 IN THE EXEC MAP
CLRPGT (0,.ECKSM) ;CLEAR THE AM ENTRY
MOVEI T1,.ECKSM ;T1 = EXEC VIRTUAL ADDRESS OF WORD 0 OF THE
; HIGH SEGMENT
POPJ P, ;RETURN
SUBTTL UUOCON - UUO HANDLING ROUTINES
IFN FTDAEM,<
;SUBROUTINE TO DO PROCESSOR DEPENDANT PORTION OF JOB PEEK UUO
;CALLING SEQUENCE:
; HRRI T4,0 IF SOURCE SEGMENT IS A SPY SEGMENT
; MOVE P1,FLAGS,,JOB NUMBER (FLAGS BIT0=0 IF READ, 1 IF WRITE)
; MOVE P2,NUMBER OF WORDS TO TRANSFER
; PUSHJ P,JOBPKD
; ALWAYS RETURN HERE
JOBPKD::PUSHJ P,GETWDU## ;GET SOURCE AND DESTINATION ADDRESSES
MOVSI T2,(PXCT 5,) ;ASSUME SOURCE AND TARGET ADDRESSES ARE IN JOB DOING
CAIN J,(P1) ; THE JOBPEK (IF SO BOTH ARE ADDRESSABLE). ARE THEY?
JRST JOBPK3 ;YES, BLT FROM USER TO USER
MOVSI T2,(PXCT 4,) ;ASSUME THE SOURCE SEGMENT IS A SPY SEGMENT
TRNN T4,-1 ; I.E., THE MONITOR. IS IT?
JRST JOBPK3 ;YES, BLT FROM MONITOR TO USER
HRRZ T2,JBTUPM##(P1) ;ADDRESS OF THE TARGET JOB'S UPMP
TRO T2,PM.ACC+PM.WRT;ALLOW ACCESS AND WRITING
HRRM T2,.UPMP+.MTEMP ;MAKE THE TARGET JOB'S UPMP ADDRESSABLE
CLRPGT (0,.JBPK) ;CLEAR THE AM FOR THIS PAGE
HRRZ T3,T1 ;DESTINATION ADDRESS IF WRITING
TLNN P1,400000 ;WRITING?
HLRZ T3,T1 ;NO, READING. GET SOURCE ADDRESS
TLNE P1,200000 ;READING THE UPMP?
MOVSI T3,1 ;YES, VIRTUAL PAGE NUMBER 1000
MOVE T2,T3 ;GET ADDRESS IN TARGET JOB
ANDI T2,PG.BDY## ;KEEP ONLY REL WD IN PAGE
ADDI T2,PG.BDY##(P2) ;ADD AND ROUND NO. WDS TO TRANSFER
LSH T2,W2PLSH## ;MAKE NO. OF PAGES
LSH T3,W2PLSH## ;CONVERT TO VIRTUAL PAGE NUMBER
MOVNS T2 ;MINUS NUMBER OF PAGES TO MAKE ADDRESSABLE
HRL T2,T3 ;STARTING VIRTUAL PAGE NUMBER IN TARGET JOB
MOVSS T2 ;MAKE AN AOBJN POINTER
ROT T3,-1 ;INDEX INTO TARGET JOB'S MAP (REMAINDER IN HIGH BIT)
MOVEI T4,.TEMP(T3) ;FORM A BYTE POINTER TO THE TARGET JOB'S MAP
HRLI T4,442200 ;ASSUME AN EVEN STARTING PAGE
SKIPGE T3 ;IS IT AN EVEN PAGE?
HRLI T4,222200 ;NO, ODD
MOVEI T3,.UPMP+.MJBPK ;ADDRESS OF JOBPEK TEMPORARY SLOTS IN THE
; PER-PROCESS MAP
HRLI T3,442200 ;STARTING IN THE LEFT HALF WORD
JOBPK0: ILDB P3,T4 ;GET THE ENTRY FROM THE TARGET JOB'S MAP
IFN FTVM,<
TRNE P3,PM.ACC ;ACCESS ALLOWED?
JRST JOBPK1 ;YES, ZOOM ON
JUMPE P3,CPOPJ## ;ERROR RETURN IF PAGE DOESN'T EXIST
CAIN P3,PM.ZER ;ALLOCATED BUT ZERO PAGE?
POPJ P, ;YES, PAGE NOT IN CORE RETURN
HRRZ P3,T2 ;VIRTUAL PAGE WHICH HAS ACCESS ALLOWED OFF
IDIVI P3,^D36 ;WORD IN WSBTAB WHICH CONTAINS BIT FOR THIS PAGE
MOVE P4,BITTBL##(P4) ;BIT POSITION WITHIN THE WORD
TDNN P4,WSBTAB-.UPMP+.TEMP(P3) ;PAGE IN CORE WITH ACCESS ALLOWED OFF?
POPJ P, ;NO, JUST GIVE PAGE NOT IN CORE RETURN
LDB P3,T4 ;GET MAP ENTRY AGAIN
JOBPK1: TRO P3,PM.ACC!PM.WRT ;ALLOW ACCESS
>
IDPB P3,T3 ;STORE IT IN THIS JOB'S PER-PROCESS MAP
AOBJN T2,JOBPK0 ;MAP ENOUGH PAGES TO ALLOW THE TRANSFER
CLRPGT (0,.JBPK) ;CLEAR THE AM FOR THIS PAGE
MOVEI T2,.JBPK/1000 ;PAGE NUMBER IN THE EXEC VIRTUAL ADDRESS SPACE
TLNE P1,400000 ;READ OR WRITE?
JRST JOBPK2 ;WRITE
DPB T2,[POINT 9,T1,8] ;READ, MAKE SOURCE ADDRESS AN EXEC VIRTUAL ADDRESS
MOVSI T2,(PXCT 4,) ;READ FROM EXEC, WRITE TO USER
JRST JOBPK3 ;GO DO THE BLT
JOBPK2: DPB T2,[POINT 9,T1,26] ;WRITING, MAKE DESTINATION AN EXEC VIRTUAL ADDRESS
MOVSI T2,(PXCT 1,) ;READ FROM USER, WRITE TO EXEC
JOBPK3: ADDI P2,(T1) ;ENDING ADDRESS EQUALS NUMBER OF WORDS PLUS
; STARTING ADDRESS
HRRI T2,[BLT T1,-1(P2)] ;XCT 1, 2, OR 3 OF A BLT
XCT T2 ;MOVE THE DATA
IFN FTVM,<
AOS (P) ;INDICATE ALL PAGES WERE IN CORE AND THE DATA
; WAS TRANSFERED
>
POPJ P, ;RETURN
>
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:
INTERN PMRSET,PMRSTR,PMRRED,PMRSTP,PMRREL
;THE FOLLOWING ERROR ROUTINES ARE CALLED BY PERF. UUO FUNCTIONS
; IN KLSER, AND ARE FOUND IN UUOCON
EXTERN PREICT,PRENXC,PREIPM,PREMNS,PREMIU,PREMAS
EXTERN PREBJN,PREMNR,PREFNI,PREBFN,PREMBP
;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##(P4) ;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.PIN ;PI IGNORE IF ZERO ARG
LSH T1,<-<^L<PE.PP0>>> ;SHIFT INTO POSITION
ANDI T1,PE.PIN ;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,(1B1) ;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##(P4) ;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,777000 ;CLEAR UNWANTED BITS
TSO T4,T1 ;AND SET THE BITS
;ADD FURTHER ENABLE LOGIC HERE
MOVEM T4,.CPPAE##(P4) ;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 " "
PMRSTR: PUSHJ P,PRFCPU ;CHECK CPU SPEC, SETUP P4, MAKE SURE METER IS OWNED
POPJ P, ;SORRY, SOMETHING WENT WRONG
SKIPE .CPPMR##(P4) ;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,PIOFF ;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##(P4) ;ALSO SAVE MEMORY REFERENCE COUNT BEFORE
PUSH P,.CPMM0##(P4) ; PI SYSTEM IS TURNED BACK ON
CONO PI,PION ;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##(P4) ;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
AOS (P) ;SET FOR SKIP RETURN
PJRST RELPMR ;AND RELEASE, RETURN
;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
TLNE T1,-1 ;SKIP IF CPU0 (ONLY ONE LEGAL FOR NOW)
JRST PRENXC ;**NON EXISTANT CPU**
TLNN T3,(1B3) ;CPU TYPE MUST BE KL10 FOR THIS FUNCTION
JRST PREICT ;**IMPROPER CPU TYPE**
MOVEI P4,.C0CDB ;SETUP P4 FOR EVERYONE
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
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
JUMPN T1,PRENXC ;**NON EXISTANT CPU**
MOVEI P4,.C0CDB ;SETUP P4
PUSHJ P,HAVPMR ;DO WE OWN THE METER??
CAIA ;NO, SEE WHAT'S WRONG
JRST CPOPJ1## ;YES, RETURN
SKIPE .CPPJB##(P4) ;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,PION ;PI OFF ALREADY?
JRST REDPM1 ;YES, DON'T TURN IT ON AGAIN
PUSHJ P,REDPM1 ;NO, TURN IT ON AFTER WERE THROUGH
PJRST ONPOPJ##
REDPM1: CONO PI,PIOFF ;TURN OFF PI
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, P4
; = CPU DATA BLOCK. PRESERVES STATE OF PI SYSTEM (ON,OFF)
STRPMJ::PUSH P,.CPMJB##(P4) ;PUT METER ENABLE INTO
POP P,.CPMJ1##(P4) ;PROPER WORD
SETOM .CPPMR##(P4) ;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##(P4) ;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##(P4) ;UPDATE COUNT
DMOVEM T1,.CPMM0##(P4)
STPPJ1: SETZM .CPMJ1##(P4) ;CLEAR JOB ENABLE THAT CLOCK1 LOOKS AT
SETZM .CPPMR##(P4) ;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. NEED NOT 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##(P4) ;ALREADY OWN IT?
JRST CPOPJ1## ;YES, GOOD RETURN
AOSE .CPPRQ##(P4) ;AVAILABLE?
POPJ P, ;NO, NOT NOW.
MOVEM J,.CPPJB##(P4) ;YES, PUT OUR NAME ON THE METER
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 AL METER VARIABLES FOR SPECIFIED CPU.
; ALL AC'S PRESERVED.
RELPMR::SETZM .CPAPS##(P4) ;CLEAR PERF/ACC METER SYNC FLAG
SETZM .CPMJB##(P4) ;CLEAR MEASURED JOB
SETOM .CPMJ1##(P4) ;-1 IS FLAG FOR CLOCK1 TO STOP METER
SETZM .CPPJB##(P4) ;CLEAR OWNING JOB
SETZM .CPPAE##(P4) ;AND PERFORMANCE ENABLES
SETOM .CPPRQ##(P4) ;NOW MAKE METER AVAILABLE
POPJ P, ;ONLY RETURN
;(ALWAYS SUCCEEDS!)
;ROUTINE TO CHECK IF THE JOB IN J OWNS THE PERFORMANCE METER
; OF THE CPU WHOSE CPU DATA BLOCK ADDRESS IS IN P4.
; NEED NOT BE RUNNING ON THAT CPU.
; USED BY PERF. UUO ONLY - PRESERVES ALL AC'S.
HAVPMR::CAMN J,.CPPJB##(P4) ;OWN METER?
AOS (P) ;YES, SKIP RETURN
POPJ P, ;OR ELSE NOT.
;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
SETZM .EPHPA## ;CLEAR HI PERF COUNT
SETZM .EPLPA## ;AND LO
SETZM .CPMM0##(P4) ;CLEAR OUT MBOX COUNT ALSO
SETZM .CPMM1##(P4) ;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##(P4) ;GET JOB ENABLE CONDITION
AOJE T1,STPPMR ;IT WAS A REQUEST TO STOP METER, DO IT.
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##(P4) ;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
$LIT
KLEND: END