Trailing-Edge
-
PDP-10 Archives
-
7.01A_PCL20_KMCSRC_19830513
-
ksser.mac
There are 6 other files named ksser.mac in the archive. Click here to see a list.
TITLE KSSER - KS10 PROCESSOR DEPENDENT CODE V1041
SUBTTL DMCC/DBD 01 JUL 80
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) 1978,1979,1980,1982 BY DIGITAL EQUIPMENT CORP., MAYNARD, MASS.
;
;******************** DDS EDIT HISTORY *******************************
;
; APR83 [DDS] ADDED PCL20 CODE.
;
;***********************************************************************
;
XP VKSSER,1041
;TRACKS VERSION 274 OF KLSER
ENTRY KSSER ;LOAD KSSER IF LIBRARY SEARCH
KSSER:
SUBTTL DEFINITIONS FOR NON-EXISTENT FEATURES ON KS10
;NO ADDRESS BREAK
XP SETBRK,COMERA##
XP SETABR,CPOPJ##
XP CLRBRK,CPOPJ##
SUBTTL TRAP HANDLING AND CONTEXT SWITCHING
;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## ;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::
SETAP1::PUSHJ P,SETRP ;SETUP THE TRAP LOCATIONS (PAGE FAULT,
; ARITHMETIC, PDL OVF)
PJRST SETCNA ;SET USER ENABLES FOR NXM AND CLOCK AND
; SET THE APR PIA
;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
HRRI T2,UE.AOT ;SET DISPATCH ADDRESS
MOVEM T2,.UPMP+.UPAOT ;STORE IN UPT
MOVEI T2,UP.PDT ;IF USER NOT ENABLED FOR POV HANDLE LIKE EXEC POV
TRNE T1,AP.POV ;IS HE ENABLED?
MOVEI T2,UE.PDT ;YES, HANDLE DIFFERENTLY
MOVEM 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-UE.NXM ;CLEAR ALL BUT CLOCK, NXM, AND PARITY
HRR T1,.CPEEB## ;SET MONITOR ENABLES
MOVEI T2,@.CPAPI## ;MOVE IN APR PIA
WRPI PI.OFF ;DISALLOW INTERRUPTS WHILE CHANGING APR BITS
HLRM T1,.CPCN1## ;USER'S ENABLE BITS
HRRM T1,.CPCON## ;MONITOR'S ENABLE BITS
WRAPR (T2) ;SET PIA
WRPI PI.ON ;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:: WRPI PI.OFF ;PREVENT CLOCK INTERRUPT DURING STOP2 CODE
SETOM .CPCKF## ;SET FLAG TO INDICATE CLK INTERRUPT
; EVEN THOUGH CLK INTERRUPT IS NOT A TIME INTERRUPT
WRPI PI.ON+PI.IIO+CLKBIT## ;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: RDPI 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
;WARNING: ANY CHANGES MADE TO TSTREL SHOULD ALSO BE REFLECTED IN GETWRD & PUTWRD
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
;HERE TO PROCESS USER ARITHMETIC OVERFLOW TRAPS
SAROVF::MOVE T1,.UPMP+.UPMUP ;GET PC
MOVE T3,.JDAT+JOBENB## ;GET USER'S ENABLE BITS
TRNN T3,AP.AOV ;OVERFLOW - IS THE USER ENABLED?
TLNE T1,(XC.FOV) ;TRAP CAUSED BY FOV?
CAIA ;YES,
JRST SAROV6 ;NOT ENABLED, IGNORE IT
HRRI T3,AP.AOV+AP.FOV;ASSUME FLOATING OVERFLOW
TLNN T1,(XC.FOV) ;WAS IT A FLOATING OVERFLOW TRAP?
TRZ T3,AP.FOV ;NO, INTEGER OVERFLOW
;HERE WITH T1=PC, T3=APRENB BITS
SAROV3: TLZ T1,3637 ;CLEAR BITS FOR COMPATABILITY
MOVEM T1,.JDAT+JOBTPC## ;SAVE OLD PC
MOVEM T3,.JDAT+JOBCNI## ;LIKE CONI ON THE KA-10
MOVE T3,.JDAT+JOBENB## ;GET USER'S ENABLE BITS
TRNE T3,XP.DDU ;USER WANT TRAPS REENABLED?
JRST SAROV5 ;YES, LEAVE AS IS
HLLZS .JDAT+JOBENB## ;CLEAR USER'S ENABLE BITS SO MUST DO APRENB AGAIN
MOVSI T3,(JFCL) ;NOP
MOVEM T3,.UPMP+.UPAOT ;IGNORE ARITHMETIC TRAPS
MOVEI T3,UP.PDT
MOVEM T3,.UPMP+.UPPDT ;EXEC WILL FIELD PDL OVERFLOWS
SETZM .CPCN1## ;CLEAR POSSIBLE NXM OR CLOCK ENABLES
SAROV5: MOVEI T3,XP.CLK ;ALWAYS DISABLE CLOCK
ANDCAM T3,.CPCN1##
HRRZ T3,.JDAT+JOBAPR## ;PC IN TRAP ROUTINE?
CAIE T3,0(T1)
CAIN T3,-1(T1)
JRST SAROV7 ;YES
HRR T1,.JDAT+JOBAPR## ;GET USER'S TRAP ADDRESS
TLZ T1,(XC.OVF+XC.FOV+XC.FUF+XC.NDV+IC.BIS)
TLO T1,(XC.USR) ;INSURE PUBLIC AND USER MODE IS SET
SAROV6: MOVEM T1,.UPMP+.UPMUO ;NEW PC WITH TRAP CAUSING BITS CLEARED
MOVE P,[XWD MJOBPD##,.JDAT+JOBPDL##] ;SET UP A STACK
PUSHJ P,SCDCHK## ;CHECK IF WE SHOULD RESCHEDULE
USERAC ;SET USER AC BLOCK
JRSTF @.UPMP+.UPMUO ;EXIT TO THE USER'S TRAP HANDLER
SAROV7: MOVEM T1,.CPAPC## ;SAVE OLD PC FOR THE ERROR MESSAGE
MOVEI T1,XP.LTH ;STUCK IN LOOP BIT
HRRM T1,.CPAEF##
JRST SEPDL3
;HERE TO PROCESS EXEC STACK OVERFLOW TRAPS
SEPDLO::EXCH T1,.UPMP+.UPMUP ;GET THE PC
MOVEM T1,.CPAPC## ;SET AS ERROR PC FOR ERRCON
HRRI T1,AP.POV ;SET PUSH DOWN OVERFLOW FLAG
SEPDL1: HRRM T1,.CPAEF## ;IN .CPAEF SO ERRCON WILL GET CALLED
MOVE T1,.UPMP+.UPMUP ;RESTORE T1
SEPDL3: SETOM .CPSCF## ;SET FORCED RESCHEDULING FLAG
SETOM .CPCKF## ;AND CLOCK FLAG
WRPI CLKBIT##+PI.IIO ;REQUEST A CLOCK INTERRUPT AND TURN THE PI SYSTEM ON
CONSO PI,II.IPA ;ANY PIS 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) INSTEAD OF HERE
MOVEM P,PIPPDL ;SAVE OLD STACK POINTER
MOVEI P,PIPPDL ; AND GET NEW ONE
STOPCD .,STOP,PIP, ;++PI IN PROGRESS
$LOW
PIPPDL: EXP 0
BLOCK 1
$HIGH
;HERE TO PROCESS PAGE FAILURE TRAPS
SEILM:: RDPI .CPTPI## ;SAVE THE PI STATE
WRPI PI.OFF ;NOW INSURE THAT PI'S ARE OFF
RDUBR .CPTCX## ;SAVE THE TRAP CONTEXT
EXECAC ;WANT MONITOR'S AC BLOCK
MOVEM T1,.CPSTT## ;SAVE T1 TEMPORARILY
LDB T1,[POINT 5,.UPMP+.LMPFW,5] ;PICK UP PF CODE
CAIGE T1,20 ;IS THIS A REAL PAGE FAULT?
JRST SEILMA ;YES--GO PROCESS IT
CAIN T1,PF.IOP ;IS IT A UBA FAILURE?
STOPCD (.,STOP,UAF) ;++UNIBUS ADDRESSING FAILURE
CAIL T1,PF.PAR ;IS IT A PARITY OR NXM TRAP?
JRST PRTRP ;YES--GO PROCESS
CAIN T1,PF.PTP ;IS IT PAGE TABLE PARITY?
JRST PTPAR ;YES--GO PROCESS
STOPCD (.,CPU,IPC) ;++ILLEGAL PAGE FAILURE TRAP CODE
;HERE ON A PARITY OR NXM TRAP
PRTRP: SKIPE .CPPSP## ;CORE SWEEP IN PROGRESS?
JRST SWTRP ;YES, JUST SAVE LOCATION OF FAILURE AND DISMISS
EXCH T1,.CPSTT## ;RESTORE T1 AND SAVE TRAP CODE
MOVEM 17,.CPA17## ;SAVE AC 17
MOVEI 17,.CPA00## ;MAKE BLT POINTER
BLT 17,.CPA17##-1 ;SAVE AC'S IN CPU DATA BLOCK
MOVE P,.CPEPD## ;SET UP ERROR STACK
MOVE J,.CPJOB## ;SET UP J WITH CURRENT JOB RUNNING
MOVE T1,JBTPPN##(J) ;GET ITS PPN
MOVEM T1,.CPEJN## ; AND SAVE IT
MOVE T1,JBTNAM##(J) ;GET ITS PROGRAM NAME
MOVEM T1,.CPEPN## ; AND SAVE IT
MOVE P4,.CPSTT## ;GET THE TRAP CODE
CAIE P4,PF.NXM ;IS IT A NXM?
SKIPA P4,[UE.PEF] ;NO--SET UP PARITY ERROR FLAG
MOVEI P4,UE.NXM ;YES--SET UP NXM FLAG
AOS .CPNPT## ;COUNT TOTAL NUMBER OF PARITY/NXM TRAPS
MOVE T1,.UPMP+.LMPFP ;GET THE PAGE FAIL PC
MOVEM T1,.CPPPC## ;SAVE THE PC FOR DAEMON
MOVEM T1,.CPMPP## ;SAVE HERE IF NEEDED FOR PI 7 MESSAGES TO JOBS
MOVE T2,.UPMP+.LMPFW ;GET THE PAGE FAIL WORD
MOVEM T2,.CPPFW## ;SAVE THE PAGE FAIL WORD FOR DAEMON
TRNE P4,UE.NXM ;IS THIS A NXM?
JRST PRTRPC ;YES--THEN THERE'S NO DATA TO PICK UP
WRUBR [LG.LAB+7B11] ;NO--SET PREVIOUS ACS TO BLOCK 7
PXCT PX.MEM,[MOVE T3,0] ;PICK UP BAD DATA WORD FROM BLOCK 7
EXECAC ;RESTORE MONITOR AC SETTINGS
MOVEM T3,.CPTBD## ;SAVE BAD DATA FOR DAEMON
PRTRPC: MOVE T4,[PXCT PX.MEM,[MAP P1,(T2)]] ;SET UP PXCT OF MAP INSTRUCTION
SKIPL .CPPFW## ;IS THIS A USER CONTEXT REFERENCE?
TLZ T4,(PX.MEM,) ;NO--THEN PXCT BECOMES REGULAR XCT
XCT T4 ;DO A MAP TO TURN PF WORD INTO PHYS ADDR IN P1
MOVEM P1,.CPPBA## ;SAVE BAD PHYSICAL ADDR FOR DAEMON
TLZ P1,777760 ;GET RID OF LEFT HALF STUFF
ROT P1,W2PLSH## ;TURN RH OF P1 INTO PAGE NUMBER OF BAD LOC
MOVE T3,.CPTOS## ;GET PAGE NUMBER OF EPMP FOR THIS CPU
PUSH P,.MERPL(T3) ;SAVE 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
TRNE P4,UE.NXM ;IS THIS A NXM?
SKIPA T1,[[ASCIZ / non-existent memory trap/]] ;YES
MOVEI T1,[ASCIZ / parity trap/] ;NO
PUSHJ P,PRMPC ;ANNOUNCE ERROR
MOVEI T1,[ASCIZ /Page fail word = /]
MOVE T2,.CPPFW##
PUSHJ P,PRMHW ;PRINT THE PAGE FAIL WORD
MOVEI T1,[ASCIZ /Mapped page fail address = /]
MOVE T2,.CPPBA##
PUSHJ P,PRMHW ;PRINT THE MAP WORD (PHYS. ADDRESS)
MOVEI T1,[ASCIZ /Incorrect contents = /]
MOVE T2,.CPTBD##
TRNN P4,UE.NXM ;IF A NXM, NO DATA TO PRINT
PUSHJ P,PRMHW ;PRINT THE BAD DATA
MOVEI T1,[ASCIZ /CONI PI, = /]
MOVE T2,.CPTPI##
PUSHJ P,PRMHW ;PRINT THE CONI PI BITS
SETZ P2, ;CLEAR FLAG REGISTER
;HERE TO START RETRIES
PRTRP3: PUSHJ P,PRTRY ;REFERENCE LOCATION
JRST PRHMF ;RETRIES FAILED! HARD MEMORY FAILURE
;HERE WE KNOW WE CAN RECOVER THE USER
MOVEM T1,.CPTGD## ;SAVE THE GOOD DATA FOR ERROR REPORTING
AOS .CPSPT## ;UPDATE COUNTER OF SOFT PARITY ERRORS
;HERE IF RETRIES WERE SUCCESFUL, LOG SOFT ERROR AND DISMISS
PRTRP5: TRO P2,PFCPF0 ;INDICATE WE'RE A KS10
HRLM P2,.CPPTR## ;SAVE STATUS FLAGS FOR ERROR REPORTING
HRRM T3,.CPPTR## ;SAVE RETRY COUNT FOR ERROR REPORTING
MOVE T3,.CPTOS## ;GET .EPMP FOR THIS CPU
POP P,.MERPL(T3) ;RESTORE TEMP MAP SLOT IN THIS EPMP
MOVEI T1,[ASCIZ /Retry successful! Correct contents = /]
MOVE T2,.CPTGD
PUSHJ P,PRMHW ;PRINT SUCCESS AND GOOD DATA
MOVEI T1,EDELIM## ;GET ADDRESS OF TEXT
PUSHJ P,PRMSG ;PRINT END DELIMITER
MOVEI T1,.ERKPT ;ASSUME PARITY CODE FOR DAEMON
TRNE P4,UE.NXM ;IS THIS REALLY A NXM?
MOVEI T1,.ERKSN ;YES--GET NXM CODE
HRL T1,.CPSLF## ;THIS CPU'S CDB ADDRESS
PUSHJ P,DAEDIE## ;PUT THE ENTRY IN THE QUEUE
JRST PTXIT ;EXIT THE TRAP
;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
MOVE T2,[EXP XC.UIO+TRYBAD] ;GET TEST TRAP ADDRESS
EXCH T2,.UPMP+.LMPFN ;EXCHANGE WITH WHAT'S THERE NOW
PUSH P,.UPMP+.LMPFP ;IF A TRAP HAPPENS, HOW WE GOT HERE IS LOST
PRTY1: TRO P2,PFCPF0 ;NOTE THIS IS TEST REFERENCE
WREBR @.CPEBR## ;INVALIDATE CACHE
MOVE T1,0(P1) ;TRY THE REFERENCE
TRZ P2,PFCPF0 ;CLEAR THE REFERENCE FLAG
TRZN P2,PFCPF2 ;ERROR DURING REFERENCE?
JRST PRTY3 ;NO--GIVE A GOOD RETURN
CAIGE T3,TRPTRY ;YES--RETRY COUNT EXHAUSTED?
AOJA T3,PRTY1 ;NO--TRY AGAIN
SKIPA ;YES--GIVE AN ERROR RETURN
PRTY3: AOS -1(P) ;SET FOR SKIP RETURN
POP P,.UPMP+.LMPFP ;RESTORE OLD CONTENTS
EXCH T2,.UPMP+.LMPFN ;RESTORE STANDARD TRAP ADDRESS
POPJ P, ;EXIT
;HERE ON TRAPS OCCURING DURING RECOVERY ATTEMPTS
TRYBAD: TRNN P2,PFCPF0 ;ARE WE HERE BECAUSE OF TEST REFERENCE?
STOPCD (.,HALT,UPF) ;++UNEXPECTED PAGE FAIL
LDB T1,[POINT 5,.UPMP+.LMPFW,5] ;GET PAGE FAIL CODE
CAIGE T1,PF.PAR ;PARITY OR NXM ERROR?
STOPCD (.,HALT,WPT) ;++WRONG PARITY TRAP
TRO P2,PFCPF2 ;YES--INDICATE ERROR
AOS .UPMP+.LMPFP ;RETURN TO TEST REFERENCE + 1
JRSTF @.UPMP+.LMPFP ;GO BACK FOR ANOTHER TRY
;HERE WHEN RETRIES FROM MEMORY FAIL
PRHMF: SETZM .CPTGD## ;ZERO "GOOD DATA" SINCE WE DIDN'T GET ANY
TRNN P4,UE.NXM ;DON'T DO NEXT IF NXM
SETZM (P1) ;ZERO (AND RE-WRITE) THE ROTTEN LOCATION ALSO
PUSH P,P2 ;SAVE P2
PUSH P,T3 ;SAVE T3
PUSHJ P,PRTRY ;NOW SEE IF IT'S REALLY HARD (MEMORY BROKEN)
TDZA P1,P1 ;IT IS, SET P1 = 0
SETO P1, ;IT'S NOT, SET P1 = -1
POP P,T3 ;RESTORE T3
POP P,P2 ;RESTORE P2
MOVE T1,.CPTOS## ;GET .EPMP FOR THIS CPU
POP P,.MERPL(T1) ;RESTORE TEMP MAP SLOT IN THIS EPMP
AOS .CPHPT## ;BUMP HARD (AR/ARX) PARITY TRAP COUNT
TRO P2,PFCPF0!PFCPF1;SAY HARD ERROR AND KS10 FOR ERROR REPORTING
HRLM P2,.CPPTR## ;SAVE FLAGS
HRRM T3,.CPPTR## ;SAVE RETRY COUNT FOR ERROR REPORTING
TRNE P4,UE.NXM ;IF THIS IS A NXM, MESSAGE IS DIFFERENT
SKIPA T1,[[ASCIZ /Retry unsuccessful./]]
MOVEI T1,[ASCIZ /Retry unsuccessful. Offending location zeroed./]
PUSHJ P,PRMSG ;ANNOUNCE FAILURE
MOVEI T1,.ERKPT ;ASSUME PARITY CODE FOR DAEMON
TRNE P4,UE.NXM ;IS THIS REALLY A NXM?
MOVEI T1,.ERKSN ;YES--GET NXM CODE
HRL T1,.CPSLF## ;AND CDB ADDRESS
PUSHJ P,DAEDIE## ;CALL DAEMON TO LOG ERROR
MOVE T1,.CPPPC## ;GET THE TRAP PC
TLNE T1,(XC.USR) ;IS THE TRAP FROM USER MODE?
JRST PRHMF1 ;YES--GO KILL USER
HRRZ T1,.CPPFW## ;GET THE PROBLEM ADDRESS
SKIPGE .CPPFW## ;IS THIS A USER CONTEXT REFERENCE?
JRST PRHMF0 ;YES--GO CHECK IF AT SCHED OR PI LEVEL
MOVE T2,SYSLEN## ;NO--GET LENGTH OF MONITOR'S HIGH SEG
ADDI T2,MONORG##-1 ;FORM EVA OF THE TOP OF THE HIGH SEG
CAIL T1,MONORG## ;IS THE ERROR IN THE
CAILE T1,(T2) ; MONITOR'S HIGH SEGMENT?
JRST PRHMF0 ;NO--GO CHECK OTHER THINGS
LSH T1,W2PLSH## ;YES--FORM THE EXEC VIRTUAL PAGE NUMBER
MOVE T2,.CPPBA## ;GET THE MAPPED PHYSICAL ADDRESS
TDZ T2,[777760,,777] ;ONLY WANT BASE ADDRESS OF PAGE
PUSHJ P,PAGRPL## ;TRY TO REPLACE THIS CODE PAGE
JRST PARHLT## ;IT DIDN'T WORK
MOVEI T1,[ASCIZ /Replaced monitor code page from disk./] ;GET TEXT
PUSHJ P,PRMSG ;PRINT IT
MOVEI T1,EDELIM## ;GET END DELIMITER
PUSHJ P,PRMSG ;PRINT IT
PJRST PTXIT ;EXIT THE TRAP
PRHMF0: SETOM .CPREP## ;SET PARITY MSG FLAG IN CASE THIS IS FATAL
TRNE P4,UE.NXM ;IS THIS A NXM?
SETZM .CPREP## ;YES--SET FLAG PROPERLY
SKIPN .CPISF## ;ARE WE IN THE SCHEDULER
CONSZ PI,PI.IPA ; OR ARE WE AT INTERRUPT LEVEL?
JRST PARHLT## ;YES--SORRY BUT WE CAN'T DO A THING
SKIPGE .CPPFW## ;WAS THIS A MONITOR REF TO USER SPACE AT UUO LVL?
JRST PRHMF2 ;YES--TREAT AS USER ERROR
CAIL T1,340000 ;IS THE ERROR IN THE
CAILE T1,377777 ; USER PER PROCESS AREA?
JRST PARHLT## ;NO--IT'S IN THE MONITOR DATA BASE, FATAL!
SETZ P2, ;YES, CALL IT LOWSEG ERROR
JRST PRHMF3 ;TREAT AS FATAL USER ERROR
PRHMF1: TDNN P4,.CPCN1## ;IS USER ENABLED TO HANDLE THIS HIMSELF?
JRST PRHMF2 ;NO--GO ON
MOVE T2,JBTSTS##(J) ;YES--GET JOB STATUS WORD
TLNE T2,JACCT ;IS JOB PRIVILEGED?
JRST PRHF1A ;YES--TRAP TO HIM
MOVE T2,JBTPPN##(J) ;NO--GET HIS PPN
CAME T2,FSFPPN## ;IS IT THE OPERATOR PPN
CAMN T2,UMDPPN## ; OR THE USER MODE DIAG PPN?
JRST PRHF1A ;YES--LET'S TRAP TO HIM AS REQUESTED
JRST PRHMF2 ;NO--THEN WE IGNORE HIS TRAP REQUEST
PRHF1A: MOVEI T1,EDELIM## ;GET END DELIMITER
PUSHJ P,PRMSG ;PRINT IT
WRPI PI.ON ;TURN PI'S BACK ON
MOVE T1,.CPPPC## ;GET THE PROBLEM PC
HRRZ T3,P4 ;PUT PARITY/NXM BIT HERE
JRST SAROV3 ;GO TRAP TO USER
PRHMF2: SETZ P2, ;SET FLAG ASSUMING LOW SEG ERROR
MOVE J,.CPJOB## ;GET THE OFFENDING JOB #
SKIPG J,JBTSGN##(J) ;DOES THIS JOB HAVE A HIGH SEG?
JRST PRHMF3 ;NO--GO ON
HRRZ T1,.CPPFW## ;GET THE PROBLEM ADDRESS
CAML T1,.UPMP+.UPHSS ;IS ADDRESS IN THE USER HIGH SEGMENT?
CAMLE T1,.UPMP+.UPHSE
JRST PRHMF3 ;NO--GO ON
SETO P2, ;YES--SET FLAG INDICATING HIGH SEG ERROR
PUSHJ P,HGHPAR## ;GO PROCESS OTHER JOBS USING THIS SEGMENT
PRHMF3: JUMPN P1,PRHMF4 ;IF MEMORY IS OK, DON'T MARK OUT PAGE
LDB T1,[POINT 13,.CPPBA##,26] ;GET THE PAGE NUMBER TO MARK OFF-LINE
PUSH P,T1 ;SAVE PAGE NUMBER
IDIVI T1,^D36 ;COMPUTE NXMTAB INDEX AND BITTBL INDEX
MOVE T2,BITTBL##(T2) ;GET CORRECT BIT TO SET
IORM T2,NXMTAB##(T1) ;MARK OUT PAGE IN NXMTAB
MOVEI T1,[ASCIZ /Location still bad after zeroing.
Setting off-line physical page /] ;GET TEXT
POP P,T2 ; AND PAGE NUMBER
PUSHJ P,PRMOC ;TELL HIM WHAT WE DID
MOVE T1,[.CSCPO,,.ERCSC]
PUSHJ P,DAEDIE## ;LOG CONFIGURATION CHANGE
PRHMF4: MOVEI T1,EDELIM## ;GET END DELIMITER
PUSHJ P,PRMSG ;PRINT IT
MOVE J,.CPJOB## ;GET JOB NUMBER
JUMPE P2,PRHMF5 ;GO STOP THIS JOB IF LOW SEG ERROR
MOVEI T1,JS.MPE ;DID HGHPAR SAY THAT THIS JOB
TDNE T1,JBTSTS##(J) ; COULDN'T BE SAVED?
JRST PRHMF5 ;YES--JUST GO STOP IT
WRPI PI.ON ;NO--TURN PI'S BACK ON
HLLZ T1,.CPMPS## ;GET CPU REQUESTS MEMORY SCAN BITS
HRRI T1,(P4) ;SET PARITY OR NXM BIT
IORM T1,.CPAEF## ;SET REQUEST
MOVE P,[XWD MJOBPD##,.JDAT+JOBPDL##] ;DUMMY STACK FOR WSCHED
PUSH P,.UPMP+.LMPFP ;STACK RETURN USER ADDRESS FOR WSCHED
PJRST WSCHED## ;RESCHEDULE THIS JOB TO RE-RUN WITH NEW HIGH SEG
PRHMF5: MOVSI T1,JACCT ;CLEAR JACCT SO DAMAGED PROGRAM
ANDCAM T1,JBTSTS##(J) ; WON'T HAVE PRIVILEGES
MOVEI T1,JS.MPE ;ASSUME PARITY ERROR IN JOB
TRNE P4,UE.NXM ;IS IT A NXM?
MOVEI T1,JS.NXM ;YES--GET NXM IN JOB STATE BIT
IORM T1,JBTSTS##(J) ;SET IN JOB STATUS WORD
HLLZ T1,.CPMPS## ;GET CPU REQUESTS MEMORY SCAN BITS
HRRI T1,(P4) ;SET PARITY OR NXM BIT
IORM T1,.CPAEF## ;SET REQUEST FOR PI 7
SETOM .CPSCF## ;FORCE RESCHEDULE
SETOM .CPCKF## ;SET FLAG FOR PI 7 INTERRUPT
WRPI XI.RQC## ;REQUEST PI 7
WRPI PI.ON ;ALLOW INTERRUPTS NOW (MAINLY PI 7)
PJRST ESTOP## ;GO STOP THIS JOB
;HERE ON TRAP DURING PARITY SWEEP
SWTRP: EXCH T1,.CPSTT## ;RESTORE T1, SAVE TRAP CODE
PUSH P,T1 ;SAVE T1
HRRZ T1,.UPMP+.LMPFP ;GET PC OF TRAP
CAIE T1,CPSMPI ;BETTER MATCH THE SWEEP BLT ADDRESS
STOPCD (.,HALT,NPI) ;++NOT PARITY INSTRUCTION
MOVE T1,.UPMP+.LMPFW ;GET THE PAGE FAIL WORD
MOVEM T1,.CPPFW## ;AND SAVE IT
WRUBR [LG.LAB+07B11] ;SET PREVIOUS AC BLOCK TO 7
PXCT PX.MEM,[MOVE T1,0] ;GET BAD DATA WORD FOR DAEMON
EXECAC ;RESTORE MONITOR'S AC BLOCK
MOVEM T1,.CPTBD## ;SAVE BAD DATA
SETOM .CPPTH## ;INDICATE ERROR ON SWEEP
MOVEI T1,3 ;BUMP RETURN PC BY 3 TO
ADDM T1,.UPMP+.LMPFP ; INDICATE A TRAP HAPPENED
POP P,T1 ;RESTORE T1
JRST PTXIT1 ;EXIT BACK TO SWEEP ROUTINE
;ROUTINE TO PRINT A MESSAGE PREFIXED BY "CPUx" AND
;FOLLOWED BY "AT EXEC(USER) PC XXXXXX"
; T1=MESSAGE ADDRESS
PRMPC: PUSHJ P,SAVE1## ;SAVE P1 TO REMEMBER ADDRESS OF MESSAGE
MOVE P1,T1 ;SAVE
PUSH P,.CPTOA## ;SAVE COMMAND OUTPUT ADDRESS
MOVEI T2,CTYWAT## ;GET ONE THAT DOESN'T USE PI SYS
MOVEM T2,.CPTOA##
MOVEI T1,SDELIM## ;GET ADDRESS OF TEXT
PUSHJ P,CONMES## ;PRINT START DELIMITER
MOVE T2,.CPLOG## ;GET THIS CPU'S NAME
PUSHJ P,PRNAME## ;PRINT IT
MOVE T1,P1 ;GET ADDRESS OF MESSAGE IN T1
PUSHJ P,CONMES## ;PRINT MESSAGE
MOVE T2,.CPPPC## ;GET SAVED PC
PUSHJ P,PCP## ;PRINT "AT EXEC/USER XXXXXX"
MOVEI T1,[ASCIZ / on /] ;SEPARATE FROM DATE/TIME
PUSHJ P,CONMES## ;PRINT IT
PUSHJ P,DAYTIM## ;PRINT DATE AND TIME
MOVEI T1,[ASCIZ /Job/];TELL THEM WHO WAS RUNNING
PUSHJ P,CONMES## ;PRINT "JOB"
PUSHJ P,PRJBNM## ;PRINT JOB INFO
MOVEI T1,[ASCIZ / was running
/]
PUSHJ P,CONMES## ;PRINT "WAS RUNNING"
PRMPC2: POP P,.CPTOA## ;RESTORE SCNSER ADDRESS
POPJ P, ;RETURN
;ROUTINES TO PRINT A MESSAGE FOLLOWED BY NUMBER IN HALFWORD OR OCTAL FORMAT
; T1=MESSAGE ADDRESS, T2=NUMBER
PRMOC: PUSHJ P,SAVE3## ;SAVE P1-P3
MOVEI P3,OCTPNT## ;GET ADDRESS OF OCTAL PRINT ROUTINE
JRST PRMHW1 ;GO TO COMMON CODE
PRMHW: PUSHJ P,SAVE3## ;SAVE P1-P3
MOVEI P3,HWDPNT## ;GET ADDRESS OF HALFWORD PRINT ROUTINE
PRMHW1: MOVE P1,T1 ;SAVE
MOVE P2,T2 ;SAVE
PUSH P,.CPTOA## ;SAVE COMMAND OUTPUT ADDRESS
MOVEI T2,CTYWAT## ;GET ONE THAT DOESN'T USE PI SYS
MOVEM T2,.CPTOA##
MOVE T1,P1 ;GET ADDRESS OF MESSAGE IN T1
PUSHJ P,CONMES## ;PRINT MESSAGE
MOVE T1,P2 ;GET NUMBER TO PRINT (IF ANY)
PUSHJ P,(P3) ;PRINT NUMBER IN DESIRED FORMAT
PUSHJ P,CRLF## ;END WITH CRLF
PJRST PRMPC2 ;FINISH UP
;ROUTINE TO PRINT A MESSAGE
; T1=MESSAGE ADDRESS
PRMSG: PUSHJ P,SAVE2## ;SAVE P1,P2 TO REMEMBER ADDRESS OF MESSAGE
MOVE P1,T1 ;SAVE
PUSH P,.CPTOA## ;SAVE COMMAND OUTPUT ADDRESS
MOVEI T2,CTYWAT## ;GET ONE THAT DOESN'T USE PI SYS
MOVEM T2,.CPTOA##
MOVE T1,P1 ;GET ADDRESS OF MESSAGE IN T1
PUSHJ P,CONMES## ;PRINT MESSAGE
PUSHJ P,CRLF## ;END WITH CRLF
PJRST PRMPC2 ;FINISH UP
;HERE ON PAGE TABLE PARITY TRAP (PF CODE 25)
PTPAR: WREBR @.CPEBR## ;CLEAR THE PAGE TABLE
AOS .CPPTP## ;COUNT A PAGE TABLE PARITY ERROR
MOVE T1,.CPSTT## ;RESTORE T1
MOVEM T1,.CPA17## ;SAVE 17
MOVEI 17,.CPA00## ;MAKE BLT POINTER
BLT 17,.CPA17##-1 ;SAVE ACS IN CPU DATA BLOCK
MOVE P,.CPEPD## ;SET UP ERROR STACK
SKIPGE T1,.CPPTF## ;PICK UP COUNT OF PAGE TABLE FAILURES
MOVEI T1,^D10 ;NONE YET, INITIALIZE
SOSG T1 ;IF COUNT HASN'T EXPIRED, JUST RETRY.
; COUNTER IS RESET ON EVERY CLOCK TICK.
STOPCD .,HALT,PTP, ;++PAGE TABLE PARITY
MOVEM T1,.CPPTF## ;REMEMBER COUNTER
MOVE T1,.UPMP+.LMPFP ;GET PAGE FAIL PC
MOVEM T1,.CPPPC## ;SAVE FOR PRINT ROUTINE
MOVE J,.CPJOB## ;SET UP J WITH CURRENTLY RUNNING JOB
MOVEI T1,[ASCIZ / page table parity trap/]
PUSHJ P,PRMPC ;ANNOUNCE ERROR
MOVEI T1,[ASCIZ /Page fail word = /]
MOVE T2,.UPMP+.LMPFW
PUSHJ P,PRMHW ;PRINT THE PAGE FAIL WORD
MOVEI T1,[ASCIZ /CONI PI, = /]
MOVE T2,.CPTPI##
PUSHJ P,PRMHW ;PRINT THE CONI PI BITS
MOVEI T1,EDELIM## ;GET ADDRESS OF TEXT
PUSHJ P,PRMSG ;PRINT END DELIMITER
PTXIT: MOVSI 17,.CPA00## ;BLT POINTER TO RESTORE ACS
BLT 17,16 ;RESTORE ACS
MOVE 17,.CPA17## ;AC 17 ALSO
PTXIT1: WRUBR .CPTCX## ;RESTORE THE CONTEXT AT TIME OF TRAP
EXCH T1,.CPTPI## ;GET PI'S AT TRAP ENTRY, SAVE T1
TRNE T1,PI.ON ;WERE THE PI'S ON?
WRPI PI.ON ;YES--TURN PI'S BACK ON
EXCH T1,.CPTPI## ;RESTORE T1
JRSTF @.UPMP+.LMPFP ;RESTORE FLAGS AND RETURN
;HERE TO HANDLE A PAGE FAULT
SEILMA: MOVE T1,.CPSTT## ;RESTORE T1
WRPI PI.ON ;RESTORE THE PI SYSTEM
SKIPN .CPEJ1## ;SKIP NEXT IF EXEC PAGE FAULT IN PROGRESS
DMOVEM T1,.CPST1## ;SAVE T1 AND T2 IN CASE OF CRASH
MOVE T1,.UPMP+.LMPFP ;GET THE PC
MOVEM T1,.CPAPC## ;STORE IT AS POTENTIAL ERROR PC
MOVEM T1,.UPMP+.UPMUP ;STORE WHERE KI WOULD PUT IT
MOVE T2,.UPMP+.LMPFW ;GET THE USER PAGE FAIL WORD
MOVEM T2,.CPPFW## ;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
JRST SEILM7 ;YES--EXEC ILL MEM REF, CHECK FOR ERJMP
SEILM0: MOVE P,[XWD MJOBPD##,.JDAT+JOBPDL##] ;SETUP A PUSH DOWN LIST
SKIPN .CPJOB##
STOPCD .,CPU,PFN ;++PAGE FAULT IN NULL JOB
PUSH P,T1 ;SAVE USER'S PC
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
MOVE T4,.JDAT+JOBENB## ;GET APR ENABLE BITS
TRNE T4,AP.ILM ;IS USER ENABLED?
JRST SUILM ;YES--DO SUILM INSTEAD
MOVE T4,T1 ;PC WORD INTO T4 FOR USRFLT
HRRI T1,AP.ILM ;ILLEGAL MEMORY REFERENCE
PUSHJ P,USRFLT## ;SEE IF PAGE FAULT FOR A VM USER
; WILL NOT RETURN IF SO (DISPATCH TO USER)
MOVEM T4,.CPAPC## ;STORE ERROR PC
MOVE T2,.CPST2## ;RESTORE T2
JRST SEPDL1 ;GO SAY "ILL. MEM. REF."
;HERE IF AN ILL MEM REF OCCURED IN EXEC MODE, CHECK FOR ERJMP OR
;ERCAL BEFORE CALLING IT AN IME
SEILM7: CONSO PI,PI.IPA ;AT INTERRUPT LEVEL?
JRST SEJLM2 ;NO, UUO LEVEL, OK
CONSO PI,PI.IPA-PI.IP7 ;YES - LEVEL 7?
SKIPN .CPISF## ;YES, FROM SCHEDULER?
JRST SEILME ;PI1 - PI6 OR NON-SCHEDULER PI7
SEJLM2: SKIPE .CPEJ1## ;NESTING?
JRST SEILM8 ;YES, IT'S AN IME
MOVE T2,.CPPFW## ;NO, GET PAGE FAULT WORD
IFN FTPEEK,<
SKIPG T2 ;USER REFERENCE?
PUSHJ P,[PUSHJ P,SAVT## ;YES, SAVE VOLATILE ACS
HRRZ T1,T2 ;VIRTUAL ADDRESS
LSH T1,W2PLSH## ;PAGE NUMBER
PUSHJ P,TSSPT## ;FAULT ON A SPY PAGE?
POPJ P, ;NO
PJRST UADERR##] ;YES, BLAME THE USER
>
DMOVEM T1,.CPEJ1## ;"TOP LEVEL", REMEMBER IN CASE WE NEST
MOVEM T1,.CPEJ3## ;ALSO SAVE HERE FOR PSYCHOPATHIC CASES
SKIP (T1) ;TOUCH PAGE FAULT PC LOCATION AND
LDB T2,[POINT 13,1(T1),12] ;GET INSTRUCTION FOLLOWING
; IF THE PC JUMPED OFF INTO THE BOONIES
; THEN THIS WILL PAGE FAULT AND WE WILL
; KNOW WE HAVE A REAL IME
CAIE T2,<ERJMP>_-^D23 ;IS IT AN ERJMP?
JRST SEILM8 ;NO, THEN WE HAVE AN IME
MOVE T2,1(T1) ;GET ENTIRE ERJMP EXPRESSION
MOVEM T2,.CPEJ4## ;AND SAVE IT WHERE WE CAN FIND IT
DMOVE T1,.CPST1## ;RESTORE FULL AC SET
MOVEI T1,@.CPEJ4## ;GET "E" OF ERJMP
; IF THIS IME'S (NOTE .CPEJ1 STILL
; NON-ZERO) THEN .CPEJ3 HAS ORIGINAL
; TRAP PC WHICH STARTED THIS MESS.
HRRM T1,.CPAPC## ;SET FROM WHENCE TO CONTINUE
MOVE T1,.CPST1## ;RESTORE T1 AGAIN
SETZM .CPEJ1## ;CLEAR NESTING FLAG
JRSTF @.CPAPC## ;AND GO PROCESS THE ERROR
;HERE ON NESTED IME, "RESTORE" THE FIRST IME AND STOPCD
SEILM8: DMOVE T1,.CPEJ1## ;PAGE FAULT PC AND REASON WORDS
MOVEM T1,.CPAPC## ;SET TRUE ERROR PC
MOVEM T1,.UPMP+.LMPFP ;ALSO MAKE UPMP LOOK RIGHT
MOVEM T2,.CPPFW## ;SET TRUE PAGE FAULT WORD
MOVEM T2,.UPMP+.LMPFW ;ALSO MAKE UPMP LOOK RIGHT
SEILME: SETZM .CPEJ1## ;CLEAR NESTING FLAG
STOPCD .+1,JOB,IME, ;++ILL MEM REF FROM EXEC
DMOVE T1,.CPST1## ;AND THE TEMP ACS USED
JRSTF @.CPAPC## ;RETURN
;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## ;GET THE ADDRESS OF THE USER'S JOB DATA AREA
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)
MOVEI T3,AP.ILM ;SET ILM BIT FOR USER
JRST SAROV3 ;FINISH UP
SUPDLO::MOVE T1,.UPMP+.UPMUP ;GET ERROR PC
MOVEI T3,AP.POV ;SET POV BIT FOR USER
JRST SAROV3 ;FINISH UP
;ONCE A SECOND TASKS FOR KS10'S
KSSEC::
;HERE ONCE A SECOND TO BE SURE UBA'S DIDN'T LOSE ASSIGNMENTS
MOVEI T2,UBA1PI## ;PI'S FOR UBA #1
MOVEI T1,UNBSTW ;UBA STATUS REGISTER ADDRESS
HRLI T1,1 ;DO UBA #1
PUSHJ P,UBACHK ;CHECK IT
MOVEI T2,UBA3PI## ;PI'S FOR UBA #3
HRLI T1,3 ;DO UBA #3
PUSHJ P,UBACHK ;CHECK IT
;***************************************************************
;PATCH TO CHECK PI ASSIGNMENT ON UBA #4 (PCL UBA)
;PART 1 OF 1
;INSTALLED BY JOHN FRANCIS 4-DEC-80 15:45
;THREE LINES OF CODE INSERTED
MOVEI T2,UBA4PI## ;PI'S FOR UBA #4
HRLI T1,4 ;DO UBA #4
PUSHJ P,UBACHK ;CHECK IT
;***************************************************************
JRST KSSEC2 ;GO TO NEXT TASK
UBACHK: PUSHJ P,UBGOOD ;IS UBA ALIVE?
POPJ P, ;NO--THEN DON'T TRY TO ACCESS IT
RDIO T3,(T1) ;YES--GET UBA STATUS
ANDI T3,UNBDTR!77 ;MASK OFF EXTRA BITS
IORI T2,UNBDTR ;SET DISABLE XFER BIT FOR COMPARE/SET
CAMN T3,T2 ;ARE ALL THE BITS RIGHT ?
POPJ P, ;ALL OK
STOPCD (.+1,DEBUG,ULP) ;++UBA LOST ITS PI ASSIGNMENT
WRIO T2,(T1) ;REASSIGN LEVELS
POPJ P,
;HERE ONCE/SECOND TO COUNT THE KEEP ALIVE COUNTER FOR THE 8080 FRONT END
KSSEC2: LDB T1,BKPALV ;GET THE CURRENT COUNT
AOS T1 ;INCREMENT IT
CAILE T1,377 ;WE COUNT IT MODULO 8-BITS
SETZ T1,
DPB T1,BKPALV ;PUT IT IN ITS PROPER PLACE
POPJ P, ;RETURN
BKPALV: POINT 8,RLWORD,27 ;BYTE POINTER TO KEEP ALIVE COUNT
;ROUTINES TO TURN KEEP ALIVE FUNCTION ON AND OFF WITH 8080 FRONT END
$LOW
ENAKAL::PUSH P,T1 ;SAVE T1
MOVSI T1,(KPACT) ;KEEP ALIVE ACTIVE BIT
IORM T1,RLWORD ;SET IT
PJRST DISKA1 ;RETURN
DISKAL::PUSH P,T1 ;SAVE T1
MOVSI T1,(KPACT) ;KEEP ALIVE ACTIVE BIT
ANDCAM T1,RLWORD ;CLEAR IT
DISKA1: POP P,T1 ;CAN'T USE TPOPJ SINCE
POPJ P, ; WE MAY NOT BE MAPPED
$HIGH
;ROUTINE TO SET HARDWARE AND SOFTWARE RELOCATION INFORMATION FOR CURRENT USER
;CALLING SEQUENCE:
; PUSHJ P,SETREL
; ... RETURN HERE
;J = CURRENT JOB NUMBER
;R = PROTECTION,,RELOCATION FOR THE LOW SEGMENT
SETRLH::MOVE J,.CPJOB## ;J=CURRENT JOB NUMBER
MOVEI T1,0
DPB T1,JBYHSS## ;FORCE MAP TO BE REDONE
SETREL::MOVE J,.CPJOB## ;J = CURRENT JOB NUMBER
SETRL1::MOVE R,JBTADR##(J) ;R = XWD PROTECTION,,EXEC VIRTUAL ADDRESS
; OF THE FIRST PAGE OF THE LOW SEGMENT
MOVEM R,.CPADR## ;SET .CPADR FOR QUICK ACCESS AT APR LEVEL
HLRZM R,.CPREL## ;SET .CPREL FOR ADDRESS CHECKING
IFN FTTRPSET,<
SKIPE T1,.CPSTS## ;HAS TIMESHARING BEEN STOPPED VIA TRPSET
CAIE T1,(J) ;YES, IS IT THIS JOB?
JUMPN T1,SETRLZ ;NO, DON'T CHANGE THE UBR
>
SKIPE J ;NULL JOB ALWAYS HAS A UPMP
JUMPE R,SETRLZ ;THERE IS NO UPMP IF THE JOB HAS NO CORE
PUSHJ P,STEUB ;NO, SET THE USER BASE REGISTER
JUMPE R,SETRLZ ;DONE IF NULL JOB
HLRZM R,.UPMP+.UPHVA ;SET .UPHVA FOR ADDRESS CHECKING AT IRP LEVEL
LDB T2,[POINT 9,R,8];GET THE CURRENT SIZE
LDB T1,JBYLSS## ;GET THE PREVIOUS SIZE OF THE LOW SEGMENT
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
SKIPN T1,.UPMP+.UPREL ;HOLEY PROGRAM?
HLR T1,R
HRRZM T1,.JDAT+JOBREL## ;STORE HIGHEST CORE-UUO ADDRESS IN JOBREL
SKIPL T1,JBTSGN##(J) ;JOB HAVE A REAL HIGH SEGMENT?
SKIPA T1,JBTADR##(T1) ;YES
HRLZS T1 ;SIZE OF SPY SEGMENT OR ZERO IF NOT SPY SEGMENT
LDB T2,[POINT 9,T1,8];CURRENT SIZE -1 OF THE HIGH SEGMENT
SKIPE T1 ;IS THERE A SPY OR HIGH SEGEMNT?
ADDI T2,1 ;YES, ITS ACTUALLY ONE PAGE BIGGER
LDB T1,JBYHSS##
MOVSI T3,REDOMP ;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: MOVE T3,JBTPDB##+0 ;NULL JOB PDB
PUSHJ P,FNDPDS## ;SET UP W
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,(SG.LUB) ;SET THE LOAD BIT
IFN FTRTTRP,<
MOVEM T1,.CPDTO## ;SAVE FOR RTTRP INTERRUPT LEVEL USE
>
WRUBR T1 ;SETUP THE UBR
SETRL2: SKIPN R,JBTADR##(J) ;RESTORE R - JOB HAVE CORE IN CORE?
TDZA T1,T1 ;NO, MUST BE THE NULL JOB OR CORE 0
MOVE T1,.JDAT+JOBENB## ;JOB'S APR ENABLE BITS
PJRST SETCNA ;SETUP APR ENABLE BITS FOR THE USER
; NO ENABLES IF NULL JOB OR NO CORE IN CORE
;ROUTINE TO SETUP USER AND EXEC BASE REGISTERS FOR A JOB
;CALLING SEQUENCE:
; MOVE J,JOB NUMBER
; PUSHJ P,STEUB
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
TLO T1,(SG.LUB) ;REQUEST LOADING OF UBR
TRNE T1,17777 ;IS THERE A UPMP
WRUBR T1 ;SET FOR CURRENT USER AND CLEAR THE AM
JRST TPOPJ## ;RESTORE T1 AND RETURN
SUBTTL IOCSS - I/O SERVICE SUBROUTINES (UUOCON AND DEVICE ROUTINES)
;HERE TO CHECK FOR EXISTENCE OF UBA DEVICES
; CALL MOVE T1,<ADR> OF DEVICE TO CHECK
; PUSHJ P,UBGOOD
; LOSE RETURN
; WIN RETURN
UBGOOD::PUSHJ P,SAVT## ;RESPECT T REGS
SETZ T2, ;BITS FOR TIOE
MOVE T3,[EXP XC.UIO+UBNOGD] ;TEMP PAGE FAIL TRAP ADDR
RDPI T4 ;SAVE STATE OF PI'S
WRPI PI.OFF ;DISABLE INTERRUPTS
EXCH T3,.UPMP+.LMPFN ;SET TEMPORARY PAGE FAIL TRAP ADR
TIOE T2,(T1) ;CHECK FOR DEVICE
SKIPA ;FAILED
AOS (P) ;WIN
MOVEI T2,UNBNED!UNBTMO ;CLEAR NED IN UNIBUS ADAPTER
HRRI T1,UNBSTW ;GET BASIC ADDRESS OF UNIBUS
BSIO T2,(T1) ;CLEAR FLAGS
MOVEM T3,.UPMP+.LMPFN ;RESTORE TRAP VECTOR
TRNE T4,PI.ON ;WERE PI'S ON?
WRPI PI.ON ;YES--THEN ENABLE THEM
POPJ P, ;RETURN
;HERE WHEN ADDRESS IS BUM
UBNOGD: AOS .UPMP+.LMPFP ;SKIP LOSING INSTRUCTION
JRST @.UPMP+.LMPFP ;JUST RETURN(NONSKIP)
;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
RDUBR T1 ;GET THE USER 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
RDUBR 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
RDUBR T1 ;GET THE CONTENTS OF THE USER AND EXEC BASE REGISTERS
SSEU1: 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
WRUBR T1 ;RESTORE THE UBR
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,.EPRPM##(P1) ;FORM A BYTE POINTER TO THE EXEC MAP
ADD P2,.CPTOS## ;POINT AT CURRENT CPU'S MAP
TLO P2,(<POINT 18,0>) ;ASSUME AN EVEN PAGE
SKIPGE P1 ;WAS IT EVEN?
HRLI P2,(<POINT 18,0,17>) ;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,(<POINT 18,0>) ;YES, THE FIRST PAGE IS MAPPED BY THE LEFT HALF WORD
HRLI P3,(<POINT 18,0,17>) ;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 SET UP UNIBUS ADAPTER MAPPING REGISTERS FOR A GIVEN
;IOWD FOLLOWING THE PAGING OF A JOB. PRESERVES T1-T4, P3, P4.
;
;CALL MOVE T2,IOWD
; MOVEI P1,0 ;FIRST CALL
; MOVE P3,LOC OF CHANNEL DATA BLOCK
; MOVE P4,FRAME-COUNT,,CHARS/WD IF TU45
; PUSHJ P,MAPIO
;RETURN CPOPJ IF IOWD EXCEEDS AVAILABLE PAGING REGISTERS
; CPOPJ1 P2=ADDRESS OF FIRST PAGING REGISTER USED
; P1=ADDRESS OF NEXT PAGING REGISTER TO BE USED
MAPIO:: TLNN T2,-1 ;0 OR CHANNEL JUMPS ARE ILLEGAL
STOPCD CPOPJ,DEBUG,IEZ, ;++IOWD EQUALS ZERO
PUSHJ P,SVEUB ;SAVE AND SETUP UBR
PUSHJ P,SAVT## ;SAVE T REGS
PUSH P,U ;SAVE U
MOVE P1,CHNIMR##(P3) ;UBA #,,1ST ASSIGNED PAGING REGISTER
HRRZI T4,-UBAEXP(P1) ;OFFSET FROM BASE OF UBA PAGING REGISTERS
LSH T4,P2WLSH## ;CONVERT TO PAGES
MOVE U,T2 ;SAVE IOWD IN U
AOS T2 ;ACCOUNT FOR FACT THAT IOWD'S ARE ADDR-1
ANDI T2,PG.BDY## ;GET LOW 9 BITS OF STARTING ADDRESS
ADD T4,T2 ;FORM STARTING "DOUBLE-WORD" -11 ADDRESS
LSH T4,2 ;TURN INTO BYTE ADDRESS
MOVEM T4,CHNIEA##(P3) ;AND SAVE IN CHANNEL DATA BLOCK
MOVE T4,CHNMRC##(P3) ;GET MAPPING REGISTER COUNT
HRRZ T2,U ;ADDRESS-1 WHERE I/O WILL START
MOVE T3,DEVMOD(F) ;GET DEVMOD
IFE FTSPL,<
TLNN T3,DVDSK ;IF A DSK
>
IFN FTSPL,<
SKIPL DEVSPL(F) ;SPOOLED DDBS ARE ALWAYS A DSK
TLNE T3,DVDSK ;IF A DSK
CAIA
>
JUMPN T3,MAPI1B ;PROCEED IF NOT READING A HOME BLOCK
JUMPGE S,MAPI1B ;PROCEED IF NOT I/O INTO MONITOR
SKIPN DINITF## ;IN ONCE ONLY CODE?
CAIE T2,@DEVMBF##(F) ;NO--IS THIS A MONITOR BUFFER?
JRST MAPIO4 ;NO--CONTINUE
ADDI T2,<.MCFV-.FPMC>+1 ;YES--CONVERT PER PROCESS ADDRESS
JRST MAPI1C ; TO A FAKE USER VIRTUAL ADDRESS
MAPI1B: TLNE T3,DVLPT!DVCDR ;IF AN LP20 CD20
JUMPL S,MAPIO4 ; SEE IF DOING MONITOR IO AND BRANCH
MOVEI T2,1(U) ;STARTING ADDRESS
MAPI1C: 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 P2,T2 ;SAVE BYTE POINTER IN P2
MOVE T2,U ;T2 AND U = IOWD
HLROS U ;U = -WORD COUNT
LDB T3,P2 ;T3 = CURRENT ABSOLUTE PAGE NUMBER
MAPIO2: TRNN T3,PM.ACC
IFN FTEXE,<
SKIPGE USRHCU## ;IF A SAVE IS IN PROGRESS,
SKIPA ; THEN, THIS IS OK
>;END OF IFN FTEXE
STOPCD .,JOB,AAO, ;++ACCESS ALLOWED IS OFF
; IOWD HAS BEEN ADDRESS CHECKED)
TRZ T3,760000 ;MASK OUT ACCESS BITS
PUSHJ P,SETUBB ;GO SET PROPER UBA BITS IN T3
WRIO T3,(P1) ;AND LOAD THE PAGING RAM
JUMPE T2,MAPIO3 ;IF ZERO, DO WHOLE PAGE
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 U,T2 ;ADD -NUMBER OF WORDS ON THIS PAGE
ADD T1,T2 ;ACCUMULATE IN TOTAL WORD COUNT
JUMPGE U,MAPIO6 ;JUMP IF THE ORIGIONAL WORD COUNT IS EXHAUSTED
ILDB T3,P2 ;T3 = NEXT PAGE NUMBER WITHIN SEGMENT
MOVEI T2,0 ;START NEXT PAGE AT ADDRESS 0
ADDI P1,1 ;POINT TO NEXT MAPPING REGISTER
SOJG T4,MAPIO2 ;CONTINUE IF THERE IS ROOM
JRST MAPI5A ;WHOOPS! OUT OF PAGING REGISTERS
;HERE IF MONITOR I/O, STILL MUST BE MAPPED
MAPIO4: TRNE T2,-1 ;ZERO ADDRESS? (I.E. NO DATA XFER)
JRST MAPI4A ;NO--PROCEED
MOVEI T2,CHNDBF##-1(P3) ;YES--SET ADDRESS TO DUMMY 1-WORD AREA
SETOM CHNNXF##(P3) ;SET NO-XFER FLAG
MAPI4A: HLROS U ;U = -WORD COUNT
MOVEI T3,1(T2) ;ACCOUNT FOR FACT THAT IOWD'S ARE ADDRESS-1
LSH T3,W2PLSH## ;CONVERT TO PAGE NUMBER
PUSHJ P,SETUBB ;GO SET PROPER UBA BITS IN T3
ANDI T2,PG.BDY## ;GET STARTING ADDRESS WITHIN PAGE
SUBI T2,PAGSIZ##-1 ;NUMBER OF WORDS TO DO IN THIS PAGE
SKIPN T2 ;IF ZERO, DO WHOLE PAGE WORTH
MAPIO5: MOVNI T2,PAGSIZ##
SUB U,T2 ;ACCOUNT FOR PORTION IN THIS PAGE
WRIO T3,(P1) ;LOAD UP THE MAPPING REGISTER
JUMPGE U,MAPIO6 ;DONE?
ADDI T3,1 ;NO, MONITOR PAGES ARE CONTIGOUS
ADDI P1,1 ;POINT TO NEXT MAPPING REGISTER
SOJG T4,MAPIO5 ;IF THERE IS ONE
MAPI5A: SETZ P1, ;NOPE--INDICATE NONE
STOPCD (UPOPJ##,JOB,OMR) ;++OUT OF MAPPING REGISTERS
MAPIO6: HRRZ P2,P1 ;GET LAST USER REGISTER ADDRESS
MOVNS U ;NEGATE U
ANDI U,PG.BDY## ;WORDS INTO LAST PAGE TO TRANSFER
SKIPN U ;JUST CROSSED PAGE BOUNDARY?
AOS P2 ;YES, ACCOUNT FOR IT
LSH U,2 ;MAKE INTO AN ELEVEN STYLE ADDRESS
HRRZI P2,-UBAEXP(P2) ;GET OFFSET INTO MAPPING REGISTERS
IMULI P2,UBAMUL ;MAKE INTO 11 STYLE ADDRESSING
ADDB P2,U ;FORM ADDRESS OF LAST WORD TO TRANSFER
SUB U,CHNIEA##(P3) ;MINUS STARTING ADDRESS
MOVEM U,CHNBTC##(P3) ; AND SAVE THE TOTAL BYTE COUNT
SKIPGE CHNNXF##(P3) ;IS THIS A NO-XFER REQUEST?
MOVE P2,CHNIEA##(P3) ;YES--THEN ENDING ADDRESS WILL EQUAL STARTING ADDR
SKIPGE P3 ;WANT TERMINATION EXPECTED?
MOVEM P2,CHNTCW##(P3) ;STORE FOR LATER CHECKING
MOVE P2,CHNIMR##(P3) ;GET ADDRESS OF INITIAL MAPPING REGISTER
PJRST UPOPJ1## ;SKIP RETURN
;ROUTINE TO SET THE PROPER BITS FOR A UBA PAGING RAM ENTRY WHICH IS IN T3.
;THE BIT SETTINGS DEPEND ON WHAT KIND OF A DEVICE IS BEING RUN THROUGH MAPIO.
SETUBB: PUSHJ P,SAVE1## ;SAVE P1
MOVE P1,DEVMOD(F) ;PICK UP DEVICE CLASSES
TRO T3,UNBVBT ;ALWAYS SET VALID
SKIPE CHNRRV##(P3) ;ARE WE DOING A READ REVERSE OPERATION?
TRO T3,UNBRRV ;YES--SET READ REVERSE
SKIPL DEVSPL(F) ;SPOOLED DDB'S ARE ALWAYS DISKS
TLNE P1,DVDSK ; OR IF A "REAL" DISK DDB
TRO T3,UNB36B ; SET FAST XFER MODE
SKIPGE DEVSPL(F) ;IF A SPOOLED DDB (I.E. DISK)
POPJ P, ; WE'RE DONE
TLNE P1,DVLPT!DVCDR ;IF AN LP20 OR CD20
TRO T3,UNBD18 ; SET 18 BITS DISABLE (16 BIT MODE)
POPJ P, ;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
WRPI 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
WRPI 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
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?
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,1000 ;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
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
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
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,0
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.
CSDMP:: WREBR @.CPEBR ;CAUSE CACHE FLUSH
AOS .CPCSN## ;COUNT THE SWEEP
POPJ P, ;RETURN
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,.CPJOB## ;CURRENT JOB NUMBER
MOVEM R,JBTADR##(P3) ;STORE PREVIOUS PROTECTION,,JDAT IN CASE OF ERROR
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,.JDAT+SGAEXT## ;FILE EXTENSION
SUBI T4,'SHR' ;T4=0 IF THE HIGH SEGMENT IS SHARABLE
PJRST NREMAP## ;REMAP IT
;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
MAPWRD::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,(<POINT 18,0,17>) ;ASSUME WORD IN EVEN PAGE
SKIPGE T2 ;IS IT?
HRLI T1,(<POINT 18,0,35>) ;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/PAGSIZ## ;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:
; PUSHJ P,MAPLOC
; RETURN HERE
; C(T1) := BYTE PNTR TO EPMP SLOT
; C(T3) := RELATIVE PAGE # IN EPMP
MAPLOC::RDPI T1 ;GET PIS IN PROGRESS
ANDI T1,II.IPA ;CLEAR ALL BITS EXCEPT PIS IN PROGRESS
JFFO T1,MAPLO1 ;FIND OUT THE HIGHEST PI IN PROGRESS, I.E.,
; THE ONE THAT THIS CODE IS BEING EXECUTED AT
MOVEI T2,34 ;MUST BE UUO LEVEL, FAKE NUMBER
MAPLO1: SUBI T2,25 ;T2=0-6 FOR PI 1-7 IN PROGRESS, 7 BY UUO LEVEL
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## ;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: PUSHJ P,@.CPMPS##
; ALWAYS RETURN WHEN SWEEP OVER (EVEN IF SERIOUS ERROR)
;SWEEP CORE IN ASCENDING ADDRESSES EVEN THOUGH SLOWER, SO DATA STORED ASCENDING
; FOR ERROR REPORTING WITH DAEMON
CPSMPS::PUSHJ P,MAPLOC ;GET EXEC MAP SLOT
MOVE W,T1 ;SAVE BYTE POINTER TO EXEC MAP SLOT
MOVEI P3,PM.ACC+PM.WRT;START AT PAGE 0, ACCESSIBLE AND WRITEABLE
LDB T4,[POINT 14,MEMSIZ##,26] ;T4=NUMBER OF PAGES TO SCAN
SKIPA P4,[POINT 1,NXMTAB##] ;BYTE POINTER TO NXM TABLE
MPSLP1: AOS P3 ;STEP TO NEXT PAGE
SOJL T4,MPSLP5 ;RESTORE T1 AND RETURN IF SCANNED ALL OF MEMORY
ILDB T1,P4 ;DOES THIS PAGE EXIST?
JUMPN T1,MPSLP1 ;IF NOT, GO BACK FOR NEXT
DPB P3,W ;MAP THE CURRENT PAGE
MOVEI P1,.ERPIL(T3) ;EVA FOR BEGINNING OF PAGE
CLRPT (P1) ;CLEAR HDW PAGE TABLE FOR NEW MAPPING
MOVEI T2,PAGSIZ## ;NO. OF WORDS/PAGE TO SCAN
WREBR @.CPEBR## ;INVALIDATE CACHE
SETOM .CPPSP## ;SET SWEEPING FLAG
CPSMPI::MOVE P2,(P1) ;TEST NEXT LOCATION
MPSLP2: SOJLE T2,MPSLP1 ;IF CURRENT PAGE DONE, MAP NEXT
AOJA P1,CPSMPI ;GO TEST NEXT WORD IN PAGE
;HERE ON BAD WORD FOUND (NXM OR PARITY) - TRAP HAPPENED AND ADDED 3 TO PC
MPSLP3: MAP T1,(P1) ;GET THE PHYSICAL ADDRESS OF BAD WORD
PUSH P,P1 ;SAVE THE EVA
PUSH P,T2 ;SAVE THE WORD NUMBER IN CURRENT PAGE
PUSH P,T3 ;SAVE THE POSITION IN THE MAP
PUSH P,T4 ;SAVE # OF PAGES TO SCAN
LDB P1,[POINT 22,T1,35] ;GET JUST THE PHYSICAL ADDRESS OF BAD WORD
PUSHJ P,CPIASN## ;CONVERT TO SEG NUMBER IN J
TDZA T1,T1 ;INDICATE NO ERROR IN MONITOR OR JOB
SETO T1, ;INDICATE AN ERROR IN MONITOR OR JOB
MOVE P2,.CPTBD## ;GET BAD DATA WORD STORED BY THE TRAP ROUTINE
PUSHJ P,PARRBD## ;RECORD BAD DATA
POP P,T4 ;RESTORE T4
POP P,T3 ; AND T3
POP P,T2 ; AND T2
POP P,P1 ; AND P1
SETZM .CPPTH## ;CLEAR FLAG THAT TRAP HAPPENED
JRST MPSLP2 ;GO CONTINUE THE SWEEP
MPSLP5: SETZM .CPPSP## ;CLEAR SWEEPING FLAG
POPJ P, ;RETURN
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
JSP T2,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
;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
MOVE T4,.CPTOS##
HRLM T3,.MEUPM(T4)
CLRPGT (0,.EUPMP) ;FLUSH PAGE TABLE SO NEW MAPPING IS IN EFFECT
;WORRY ABOUT INTERLEAVED MEMORY
MOVEI T3,MEMITL## ;NUMBER OF WAYS MEMORY CAN BE INTERLEAVED
MOVEM J,MOFLPG## ;FLAG THAT MEMORY BEING SET ON LINE
; NXM AT THIS POINT ISN'T A SERIOUS ERROR
MEMO10: MOVEI T4,20 ;TIME TO WAIT FOR NXM FLAG TO CAUSE AN IRP.
SETZM .EUPMP-1(T3) ;REFRENCE THE PAGE TO MAKE SURE ITS REALLY THERE
SOJG T4,. ;WAIT LONG ENOUGH FOR NXM INTERRUPT TO HAPPEN
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,[.CSCMO,,.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
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?
CAMN J,.CPJOB## ;CORE 0 ON THE CURRENT JOB?
DATAO PAG,NULDOP## ;YES, GIVE THE METERS SOMEPLACE ELSE TO WRITE
; SINCE THIS PAGE COULD BE ALLOCATED TO SOMEONE ELSE
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
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
PUSHJ P,SAVE1##
MOVE P1,.CPTOS##
AOS T2,T1 ;T2 = NUMBER OF WORDS OF CORE REQUIRED TO
; SATISFY REQUEST
LSH T2,W2PLSH## ;T2 = NUMBER OF PAGES REQUIRED
MOVE T3,T2
CAILE J,JOBMAX##
JRST CORG0A ;NO
LDB T3,IMGOUT##
JUMPE T3,CORG0B
LDB T3,IFYPGS##
JUMPE T3,[LDB T3,NFYPGS##
JRST CORG0C]
MOVEI T4,0
DPB T4,IFYPGS##
CAIA
CORG0B: MOVEI T3,UPMPSZ##
DPB T3,NFYPGS##
CORG0C: ADDM T2,T3 ;ADD THAT IN
CORG0A: CAMLE T3,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
DPB T2,IMGIN## ;STORE THE NUMBER OF PAGES ALLOCATED IN CORE
HRLI R,-1(T1) ;R = NEW PROTECTION,,?
CAILE J,JOBMAX##
SKIPA T2,T3
MOVEI T2,-UPMPSZ##(T3)
PUSHJ P,GTPAGS ;ALLOCATE THE PAGES TO SATISFY THE REQUEST
MOVEI T1,PM.ACC+PM.WRT+PM.CSH(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,UPMPSZ## ;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)
MOVE T2,.CPTOS##
HRLM T1,.MEUPM(T2)
CLRPGT (0,.EUPMP) ;THE UPMP IS NOW MAPPED THROUGH THE EXEC
; MAP. CLEAR THE AM SO THE NEW MAPPING
; WILL BE IN AFFECT
SETZM .EUPMP
MOVE T2,[.EUPMP,,.EUPMP+1]
BLT T2,.EUPMP+PG.BDY## ;ZERO THE ENTIRE UPMP
MOVSI T2,NUPPMT## ;NOW SETUP THE REST OF THE MAP FROM THE
HRRI T2,.EUPMP+.UPTVC ; 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
CLRPT .JDAT ;CLEAR OUT OLD ENTRY FOR .JDAT
DPB T1,JBYLSA## ;STORE FIRST PAGE OF LOW SEG IN JBTAD2
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
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)
MOVE T2,.CPTOS##
HRLM T1,.MEUPM(T2)
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
MOVEM J,.UPMP+.UPJOB ;SAVE THE JOB NUMBER FOR DEBUGGING AND
; VIRCHK (FOR GIVING BACK HIGH SEG CORE)
HLRZM R,.JDAT+JOBREL## ;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--ADD TO IN-CORE LIST
SKIPN R ;GIVING UP CORE?
PUSHJ P,DICLNK## ;YES--REMOVE FROM IN-CORE LIST
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
>
LDB T1,IMGOUT## ;CORE ALLOCATION FOR THE SWAPPER?
JUMPN T1,CPOPJ1## ;YES, ALL DONE
CAMN J,.CPJOB## ;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
CAMN J,.CPJOB## ;CURRENT JOB?
TLNN R,MPGSIZ## ; OR ONLY ONE PAGE ALLOCATED TO THE CURRENT JOB?
; IF ONLY 1 PAGE SETREL MIGHT NOT CALL MAPLOW
JUMPN R,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::
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
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,.CPJOB## ;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
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,<
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,USRPC## ;JOBS PC
TLNN T1,(XC.USR) ;JOB IN EXEC MODE?
MOVEM R,.JDAT+JOBDPG##;YES, STORE POSSIBLY UPDATED R IN THE DUMP ACS
PJRST MAPHGH ;MAP THE HIGH SEGMENT
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
;SUBROUTINE TO MAKE A PHYSICAL PAGE ADDRESSABLE FOR SWAPPER
;CALL SEQUENCE:
; MOVEI T1,PAGE NUMBER
; PUSHJ P,SWPAD
; ALWAYS RETURNS HERE
;T1=EVA OF FIRST WORD IN PAGE
SWPAD:: PUSHJ P,SAVE1##
MOVE P1,.CPTOS##
TRO T1,PM.ACC+PM.WRT;SET ACCESS BITS
HRRM T1,.MECKS(P1)
;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 FROM UUO,,JOB NUMBER
; MOVE P2,NUMBER OF WORDS TO TRANSFER
; PUSHJ P,JOBPKD
; RETURN HERE IF PAGE NOT IN CORE
; RETURN HERE IF DATA TRANSFERRED SUCCESSFULLY
JOBPKD::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
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?
TLNE P1,(JK.EVA!JK.UPM) ; AND NOT FUNNY SPACE ADDRESS
CAIA ;NO, CONTINUE
JRST JOBPK3 ;YES, BLT FROM USER 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,.TEMP) ;CLEAR THE AM FOR THIS PAGE
HRRZ T3,T1 ;DESTINATION ADDRESS IF WRITING
TLNN P1,(JK.WRT) ;WRITING?
HLRZ T3,T1 ;NO, READING. GET SOURCE ADDRESS
TLNE P1,(JK.EVA) ;ADDRESS IN EVM MAPPED THRU OTHER JOB?
ADDI T3,440000 ;YES, ADD OFFSET THAT WILL CAUSE CALCULATIONS
;BELOW TO POINT TO WORD 400 IN UPMP
TLNE P1,(JK.UPM) ;READING THE UPMP?
MOVE T3,[.UPMVP] ;YES, VIRTUAL PAGE NUMBER OF THE UPMP
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,(POINT 18,0) ;ASSUME AN EVEN STARTING PAGE
SKIPGE T3 ;IS IT AN EVEN PAGE?
HRLI T4,(POINT 18,0,17) ;NO, ODD
MOVEI T3,.UPMP+.MJBPK ;ADDRESS OF JOBPEK TEMPORARY SLOTS IN THE
; PER-PROCESS MAP
HRLI T3,(POINT 18,0) ;STARTING IN THE LEFT HALF WORD
HRRI P1,.JBPK ;SETUP FIRST PAGE TO CLEAR
JOBPK0: ILDB P3,T4 ;GET THE ENTRY FROM THE TARGET JOB'S MAP
TRNE P3,PM.ACC ;ACCESS ALLOWED?
JRST JOBPK1 ;YES, ZOOM ON
JUMPE P3,JPKPNC ;ERROR RETURN IF PAGE DOESN'T EXIST
TLNN P1,(JK.EVA) ;PAGE MUST BE THERE IF EVM ADDRESS
CAIN P3,PM.ZER ;ALLOCATED BUT ZERO PAGE?
JRST JPKPNC ;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?
JRST JPKPNC ;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
CLRPGT (0,(P1)) ;CLEAR PAGE TABLE
ADDI P1,PAGSIZ## ;STEP TO NEXT PAGE
AOBJN T2,JOBPK0 ;MAP ENOUGH PAGES TO ALLOW THE TRANSFER
MOVEI T2,.JBPK/1000 ;PAGE NUMBER IN THE EXEC VIRTUAL ADDRESS SPACE
TLNE P1,(JK.WRT) ;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
JRST CPOPJ1## ;INDICATE ALL PAGES WERE IN CORE AND THE DATA
; WAS TRANSFERED AND RETURN
;ERROR CODES (MORE IN UUOCON)
ERCODE JPKPNC,JKPNC% ;PAGE NOT IN CORE
>
$LIT
KSEND: END