Trailing-Edge
-
PDP-10 Archives
-
BB-5255D-BM
-
language-sources/glxpfh.mac
There are 7 other files named glxpfh.mac in the archive. Click here to see a list.
TITLE GLXPFH - Page fault handler for the GALAXY library on the DECsystem-10
SUBTTL Dave Cornelius 16-Aug-79
;
;
; COPYRIGHT (c) 1979
; DIGITAL EQUIPMENT CORPORATION
;
; THIS SOFTWARE IS FURNISHED UNDER A LICENSE AND MAY BE USED
; AND COPIED ONLY IN ACCORDANCE WITH THE TERMS OF SUCH LICENSE
; AND WITH THE INCLUSION OF THE ABOVE COPYRIGHT NOTICE. THIS
; SOFTWARE OR ANY OTHER COPIES THEREOF MAY NOT BE PROVIDED OR
; OTHERWISE MADE AVAILABLE TO ANY OTHER PERSON. NO TITLE TO
; AND OWNERSHIP OF THE SOFTWARE IS HEREBY TRANSFERRED.
;
; THE INFORMATION IN THIS SOFTWARE IS SUBJECT TO CHANGE
; WITHOUT NOTICE AND SHOULD NOT BE CONSTRUED AS A COMMITMENT
; BY DIGITAL EQUIPMENT CORPORATION.
;
; DIGITAL ASSUMES NO RESPONSIBILITY FOR THE USE OR RELIABILITY
; OF ITS SOFTWARE ON EQUIPMENT WHICH IS NOT SUPPLIED BY
; DIGITAL.
;This module is loaded in the low segment of any program
; using the GALAXY library code, GLXLIB.
SEARCH GLXMAC ;SEARCH GLXMAC FOR SYMBOL DEFS
PROLOG(GLXPFH,PFH)
PFHEDT==2 ;EDIT LEVEL FOR MODULE
SUBTTL Table of Contents
SUBTTL Revision History
COMMENT \
Revision History
EDIT GCO DESCRIPTION
1 Create GLXPFH from the remains of GLXINI
2 Don't throw out symbols until first timer trap
And when we do throw 'em out, do it in one or two UUOs,
not one PAGE. for each page thrown out
\ ;end of revision history
SUBTTL Fault handler data space
TOPS10 < ;THIS CODE EXISTS ONLY FOR THE TOPS10 MONITOR
COMMENT \
The fault handler will live in the realm of the library.
The code which handles the faults and determines what to do
is sharable, and part of the library high segment.
Since the monitor check to see if we are executing in the fault
handler is a range check of our PC agains the limits in .JBPFH,
the code should be as low as possible in the high segment.
We load it right after the entry vector.
Included as part of the fault handler (ie inside the high and low
bounds of the monitor's range check) is 10 words of
dirty space. Since the library is sharable, these 10 words
can't live in the high segment.
We put them in a page which is just below the library high segment.
Unfortunately, LINK doesn't support relocatable PSECTs, so
alot of this 'page manipulation' magic is done at link time.
The PSECTs whose origins must be defined (at LINK time) are:
If the library is impure (ie it will live in the lowseg), then
all of this PSECT nonsense is unneccessary, and not used.
Name Location Contents
.HIGH. 400000 The library sharable, reentrant code.
PFHDAT 377000 Fault handler data page (mostly blank)
DATA 600000 Local storage for library. Library symbol table
\
IFN GLXPURE,< ;Only if we're going to be sharable...
.PSECT PFHDAT ;Into dirty PFH data space
PFHEST==32 ;Estimated size of fault handler data
;If this is wrong, assembly won't go.
;If it is too high, we'll return the
;space anyway.
BLOCK PAGSIZ-PFHEST ;Get to near top of page
>;End IFN GLXPURE
PFHDST: ;Start of the data spce
PFHBGN: JRST PFHSTA ;ENTERED HERE
PFH.PC: 0 ;PC AT TIME OF TRAP
PFH.PN: 0 ;PAGE FAULT WORD
PFH.TI: 0 ;VIRTUAL AGE OF THE PAGE FAULT HANDLER
PFH.RA: 0 ;CURRENT PAGING RATE
PFH.PV: 0 ;Highest PSI,,Adr of PSI vec
BLOCK 3 ;ROOM FOR FUTURE EXPANSION
PFHS.P: BLOCK 1 ;SAVED P
PF.PDL: BLOCK ^D12 ;PDL FOR USE IN THE PAGE FAULT HANDLER
PF.PSZ==.-PF.PDL ;SIZE OF THE LIST
NICUCN: BLOCK 1
NICCNT: BLOCK 1
GVACNT: BLOCK 1
TIMCNT: BLOCK 1
IFN GLXPURE,< ;... Only for high segments
PFHDSZ==.-PFHDST ;Size of the data space
PFHDEN: ;End of PFH data space
IFG <PFHDSZ-PFHEST>,<PRINTX ?PFH DATA SPACE TOO BIG, INCREASE PFHEST DEFINITION>
.ENDPS ;Back to the library
>;End IFN GLXPURE
>;End TOPS10
SUBTTL The Page Fault Handler (TOPS-10 Only)
;THIS IS THE ROUTINE CALLED BY THE TOPS10 SYSTEM SO THAT A USER MAY PROCESS
;HIS OWN PAGE FAULTS. .JBPFH CONTAINS THE STARTING ADDRESS OF THE ROUTINE
;AND IS CALLED WHEN EITHER A PAGE FAULT OCCURS OR THE .STTVM TIMER HAS EXPIRED
TOPS10 <
PFHSTA:
MOVEM P,PFHS.P ;SAVE SOMEBODY'S P
;*** Temporary
MOVEM P,PFHACS+P
MOVEI P,PFHACS
BLT P,PFHACS+P-1
;*** End Temporary
MOVE P,[IOWD PF.PSZ,PF.PDL] ;GET MY OWN PDL
PUSH P,P1 ;BEGIN TO SAVE SEVERAL REGISTERS
PUSH P,P2 ;CAUSE I'M GOING TO CALL SUBROUTINES
PUSH P,P3 ;FOR SWAPPING AND SEARCHING
PUSH P,P4 ;AND THESE ARE THE ARGUMENTS
LOAD P1,PFH.PC,RHMASK ;Get addr of fault
CAIL P1,PFHDST ;Skip if before fault handler
CAILE P1,PFHEND ;or was fault off end of handler
SKIPA ;Fault outside of handle
HALT . ;Oops! We're very confused
LOAD P2,PFH.PN,PF.HFC ;THE FAULT TYPE
CAIG P2,PFHDCT ;RANGE CHECK
JRST PFHDSP(P2) ;DISPATCH THE FAULT
PFHDSP: JRST PFHILL ;PAGE FAULT CODE = 0 OR TOO BIG
JRST PFHGVA ;.PFHNA = 1 = NO ACCESS
JRST PFHSWI ;.PFHNI = 2 = NOT IN CORE
JRST PFHSWU ;.PFHUU = 3 = NOT IN CORE FOR UUO
JRST PFHTIM ;.PFHTI = 4 = VM TIMER TRAP
PFHDCT==.-PFHDSP-1 ;DISPATCH LENGTH (0-n)
PFHILL: $STOP(UPF,Unknown page fault type)
PFHSWU: AOSA NICUCN ;Count 'not in core for UUO' faults
PFHSWI: AOS NICCNT ;Count 'not in core' faults
LOAD P3,PFH.PN,PF.HPN ;GET THE PAGE THAT CAUSED THE FAULT
MOVEI P2,1 ;ONLY 1 PAGE
MOVE P1,[.PAGIO,,P2] ;FUNCTION PAGE IO,,ARGUMENT BLOCK
PAGE. P1, ;SWAP IT IN
JRST PFHSWF ;FAILED, SEE WHY
MOVX P1,PT.WRK ;THE WORKING SET BIT
IORM P1,PAGTBL##(P3) ;PAGE IS NOW IN CORE
JRST PFHXIT ;DISMISS THE FAULT
PFHSWF: CAIE P1,PAGLE% ;IS MY CORE LIMIT EXCEEDED
$STOP(PIF,Page in failure)
PUSHJ P,ANYOUT ;SWAP OUT SOMETHING (ANYTHING)
JRST PFHSWI ;TRY THE SWAPIN NOW
;;;CODE IS CONTINUED ON THE NEXT PAGE AND STILL UNDER TOPS10 CONDITIONAL
;HERE TO GIVE ACCESS TO A PAGE (CAN ONLY HAPPEN IF LOADED VIA GET.SHR)
PFHGVA: AOS GVACNT
LOAD P3,PFH.PN,PF.HPN ;GET THE PAGE NUMBER WE CAN'T ACCESS
TXO P3,1B0 ;SET TO ALLOW ACCESS
MOVEI P2,1 ;ONLY ONE ARG
MOVE P1,[.PAGAA,,P2] ;GIVE ACCESS,,ARGS
PAGE. P1, ;SET ACCESS ALLOWED ON THAT PAGE
$STOP(CGA,Cannot give access to page)
JRST PFHXIT ;AND EXIT FROM THE PAGE FAULT HANDLER
;HERE ON A TIMER TRAP, SEE IF WE CAN CLEAN UP SOME CORE
PFHTIM: AOS TIMCNT
SKIPE INMEMF## ;SOMEBODY FOOLING WITH THE PAGE TABLE?
JRST PFHXIT ;Yes, don't screw 'em up
PUSHJ P,PGSDES ;NO, DESTROY ANY JUNK PAGES
PUSHJ P,PGSSWP ;And dump out any swappable pages
PFHXIT: POP P,P4 ;RESTORE ACS
POP P,P3 ;...
POP P,P2 ;...
POP P,P1 ;...
MOVE P,PFHS.P ;RESTORE THE OLD AC P
;*** Temporary
$DATA (PFHACS,20)
PFH..X==0
REPEAT 20,<
CAME PFH..X,PFHACS+PFH..X
PUSHJ P,PFHDIE
PFH..X==PFH..X+1
>
;*** End Temporary
JRSTF @PFH.PC ;DISMISS THE FAULT
;*** Temporary
PFHDIE: OUTSTR [ASCIZ/
?GLXPFH is confused. Please save this core image
/]
$STOP (PFH,GLXPFH IS CONFUSED)
EXIT 1,
POPJ P,
;*** End Temporary
SUBTTL PGSDES - Routine to destroy unused pages
;CALL IS: NO ARGUMENTS
;
;TRUE RETURN: ALWAYS
PGSDES: MOVE P4,PAGSTA## ;THE FIRST AVAILABLE PAGE
PGSD.1: CAIL P4,MEMSIZ ;OFF THE END OF THE WORLD
POPJ P, ;YES, RETURN
MOVE P1,PAGTBL##(P4) ;GET TABLE ENTRY FOR PAGE IN P4
TXC P1,PT.ADR ;NEED CHECK FOR BOTH SO FLIP
TXNN P1,PT.USE!PT.ADR ;USED OR NOT ADDRESSABEL
PUSHJ P,DESTRY ;DESTROY THE PAGE (COULD BE PAGED OUT)
AOJA P4,PGSD.1 ;AND CONTINUE LOOPING
DESTRY: MOVEI P3,(P4) ;WANT IT IN P3
TXO P3,1B0 ;SET TO DESTROY
MOVEI P2,1 ;1 ARGUMENT
MOVE P1,[.PAGCD,,P2] ;CREATE/DESTROY,,ARGUMENT
PAGE. P1, ;TRY TO DESTROY IT
$STOP(PDF,Page destroy failed)
ZERO P1 ;CLEAR A REG
EXCH P1,PAGTBL##(P4) ;CLEAR PAGE TABLE ENTRY, GET OLD
TXNE P1,PT.WRK ;JUST DESTROY AN IN-CORE PAGE
SOS AVBPGS## ;YES, REDUCE COUNTER ACCORDINGLY
POPJ P, ;RETURN
SUBTTL PGSSWP - Swap out swappable pages
;PGSSWP - This routine will try to page out any pages
; which are marked as swappable in PAGTAB but have managed to
; crawl back into the working set. This can happen for instance,
; in the case of symbols thrown out during initialization
; but faulted back in at a breakpoint by a DDT search of the symbol
; table.
PGSSWP:
PUSHJ P,INDDT ;Fault from DDT itself?
POPJ P, ;Yes, don't throw out symbols
SETZB P4,SWPTBL ;Start at page 0, With none thrown out
PGSS.1: CAIL P4,MEMSIZ ;Off the end?
PJRST PGSS.2 ;Yes, dump out any we found, and return
MOVE P1,PAGTBL(P4) ;Get entry for this page
TXNE P1,PT.WRK ;Is this one out already?
TXNN P1,PT.SWP ;No, is it swappable?
AOJA P4,PGSS.1 ;Swapped, or not a candidate, skip it
;Found a page to throw out, add it to the table
AOS P3,SWPTBL ;Get next slot number
MOVEM P4,SWPTBL(P3) ;Save page number to go out
MOVX P1,1B0 ;Set to page OUT, not in!
IORM P1,SWPTBL(P3) ;Light in arg word for UUO
MOVX P1,PT.WRK ;Get the working set bit
ANDCAM P1,PAGTBL(P4) ;This page is out! (hopefully)
CAIL P3,SWPTLN ;Just filled up table?
PUSHJ P,PGSS.2 ;Yes, throw out what we have
AOJA P4,PGSS.1 ;Then try the next one
;A routine to page out whatever has been found as swappable
PGSS.2: SKIPN SWPTBL ;Anything to do?
POPJ P, ;No, just return
MOVX P1,<XWD .PAGIO,SWPTBL> ;Aim at the block we've built
PAGE. P1, ;Dump these pages out!
CAXN P1,PAGMI% ;Lost because we're confused?
SKIPA ;Wins, keep going
$STOP (SPF,<Page out for symbols failed, error code ^O/P1/>)
SETZM SWPTBL ;Clear UUO counter
POPJ P, ;Return
;Data space for the symbol pager
SWPTLN==^D25 ;At most (usually) 25 pages of symbols
$DATA (SWPTBL,SWPTLN+1) ;UUO block, counted
SUBTTL INDDT- Routine to determine if fault occurred inside DDT
;Returns .+1 if fault happened in DDT
;Returns .+2 if fault was outside DDT
INDDT: SKIPN P1,.JBDDT ;Get end,, start of DDT
JRST INDSKP ;No DDT, skip return
HLRZ P2,P1 ;Isolate ending adrs
HRRZS P1 ;Isolate starting adrs
LOAD P3,PFH.PC,RHMASK ;Get fault PC
CAIL P3,(P1) ;Below start of DDT
CAILE P3,(P2) ;Or above end
INDSKP: AOS (P) ;Not in DDT
POPJ P, ;Give skip return
SUBTTL ANYOUT - Routine to swap out anything possible
; CALL IS: NO ARGUMENTS
;
ANYOUT: MOVE P4,PAGSTA## ;FIRST MAKE A PASS LOOKING FOR ANY FREE
ANYO.1: PUSHJ P,ANYO.4 ;PAGES THAT CAN BE DESTROYED
JUMPE P4,ANYO.2 ;NONE, PAGE SOMETHING OUT
TXNE P1,PT.USE ;IS THIS IN-CORE PAGE USED
AOJA P4,ANYO.1 ;YES, LOOK FOR ANOTHER
PJRST DESTRY ;NO, DESTROY IT NOW AN SAVE A SWAP
ANYO.2: AOS P4,SWPSTA## ;START WHERE WE LEFT OFF
PUSHJ P,ANYO.4 ;FIND A SWAPPED IN PAGE
JUMPN P4,ANYO.3 ;SWAP IT OUT
MOVE P4,PAGSTA## ;RE-START AT THE FIRST
PUSHJ P,ANYO.4 ;TRY NOW
JUMPN P4,ANYO.3 ;FOUND ONE, SWAP IT OUT
$STOP(NTS,Nothing to swap out)
ANYO.3: MOVEM P4,SWPSTA## ;REMEMBER FOR LATER
MOVE P3,P4 ;COPY THE PAGE NUMBER
TXO P3,1B0 ;SET TO SWAP OUT INSTEAD OF SWAP IN
MOVEI P2,1 ;ONLY 1 PAGE FOR NOW
MOVE P1,[.PAGIO,,P2] ;FUNCTION SWAP,,ARGUMENT BLOCK
PAGE. P1, ;OUT IT GOES
$STOP(POF,Page out failure)
MOVX P1,PT.WRK ;GET THE WORKING SET BIT
ANDCAM P1,PAGTBL##(P3) ;NOT THERE ANY MORE
POPJ P, ;AND RETURN FOR ANY RETRIES
ANYO.4: CAIL P4,MEMSIZ ;OVER THE TOP
JRST ANYO.5 ;YES, RETURN A ZERO
MOVE P1,PAGTBL##(P4) ;GET THE STATUS FLAGS FOR PAGE IN P4
TXNE P1,PT.ADR ;IS IT ADDRESSABLE
TXNN P1,PT.WRK ;YES, IS IT IN THE WORKING SET
AOJA P4,ANYO.4 ;TRY THE NEXT PAGE
POPJ P, ;YES, A CANDIDATE FOR SWAP OUT
ANYO.5: ZERO P4 ;RETURN 0 IF NONE FOUND
POPJ P, ;RETURN
PFHEND: ;THE LAST LOCATION WITHIN THE PAGE FAULT HANDLER
> ;END TOPS10 CONDITIONAL
SUBTTL SETPFH - Set up private page fault handler
;This is a no-op for TOPS-20 systems, for TOPS-10, we install
; our PFH.
;CALL IS:
; M%INIT MUST be called before coming into SETPFH, since
; we depend on PAGSTA being setup
; No arguments
;
;TRUE RETURN: Always
SETPFH::
TOPS10 <
$SAVE <P1,P2>
SETZM INMEMF## ;CLEAR FLAG
MOVE S1,[PFHEND,,PFHBGN] ;GET START AND END OF PFH
MOVES PFHBGN ;Get it in core
MOVEM S1,.JBPFH## ;STORE LOCATION OF OUR PFH
PUSHJ P,MAPCOR ;Read the state of the working set
MOVE S1,[.STTVM,,^D1000] ;SET VIRTUAL TIMER TRAP (1 SEC)
SETUUO S1, ;
JFCL ;IGNORE ANY FAILURES
MOVE S1,PAGSTA## ;GET START OF FREE SPACE
SUBI S1,1 ;BACK OFF BY ONE
MOVEM S1,SWPSTA## ;AND STORE IT FOR LATER USE
IFN GLXPURE,<
MOVEI S1,PFHDAT/PAGSIZ ;Page # of data page
MOVX S2,PT.INI ;Page in initial core image bit
ANDCAM S2,PAGTBL(S1) ;Allow returns of pieces of this page
MOVEI S1,PFHDST-PFHDAT ;Size of space at start of page
MOVEI S2,PFHDAT ;Get addr of dirty page
PUSHJ P,RETMEM ;Give back that wasted space
IFN PFHEST-PFHDSZ,<
MOVEI S1,PFHEST-PFHDSZ ;Size of that slot
MOVEI S2,PFHDEN ;Addr of small chunk above fault handler
PUSHJ P,RETMEM ;Give that back too
>
SKIPN S1,.HIGH.+.JBHSM ;Load high seg sym pointer
JRST SETP.1 ;No high seg syms, try low seg
PUSHJ P,PAGSYM ;Page out the high seg symbols
HLRE S1,.HIGH.+.JBHSM ;Get neg length of high syms
HRRZ S2,.HIGH.+.JBHSM ;And get start adr
SUB S2,S1 ;Compute the adr of first free
TXNN S2,PAGSIZ-1 ;Symbols fit exactly on a page?
JRST SETP.1 ;Just fit, don't return anything
LOAD S1,S2,PAGSIZ-1 ;Get number used in this page
SUBI S1,PAGSIZ ;Make neg number free
MOVNS S1 ;And now positive
PUSHJ P,RETMEM ;Give back that space
SETP.1:
>;End IFN GLXPURE
SKIPE S1,.JBSYM ;Load low seg symbol pointer
PUSHJ P,PAGSYM ;Page out the low seg symbols
> ;END TOPS10 CONDITIONAL
$RETT ;All done
TOPS10<
;RETMEM is used to return pieces of memory which may have been part of
; the initial core image
;Call with S1 - length of block
; S2 - adr of block
;Returns true, memory returned, page marked as not in initial allocation
RETMEM:
PUSH P,S2 ;Save adr of block
ADR2PG S2 ;Get page number
MOVX TF,PT.INI ;Get 'in initial core image' bit
ANDCAM TF,PAGTBL(S2) ;Clear, so we can RMEM
POP P,S2 ;Get back start of block
PJRST M%RMEM ;Give back the space
>;END TOPS10
TOPS10<
;PAGSYM takes a symbol table pointer in S1 <-len,,adr> and marks
; all pages which completely reside in the symbol table
; as swappable on a timer trap
PAGSYM:
$SAVE <P1,P2>
HRRZ P2,S1 ;Copy adr of block
HLRE P1,S1 ;Make negative length of table
MOVNS P1 ;And now length of table
ADD P1,P2 ;Figure first free after syms
ANDI P2,-PAGSIZ ;Get page number of first page of syms
PAGS.1: ADDI P2,PAGSIZ ;Bump to next page
CAILE P2,(P1) ;Off end of symbols?
$RETT ;Yes, stop the page out war
MOVE S1,P2 ;Get addr of page to move out
ADR2PG S1 ;Make it a page number
MOVX S2,PT.SWP ;Get 'swappable anytime' bit
IORM S2,PAGTBL(S1) ;Mark it as such
JRST PAGS.1 ;Try the next page
> ;END TOPS10 CONDITIONAL
SUBTTL MAPCOR - Read the page map bits from the monitor
;This routine will ask the monitor for the state of the working
; set and will set or clear the PT.WRK bits in PAGTBL
TOPS10<
MAPCOR:
$SAVE <P1,P2>
MOVX S1,MAPLEN ;Length of table
MOVEM S1,BITMAP ;Count it for the monitor
MOVE S1,[XWD .PAGWS,BITMAP] ;Read working set into BITMAP
PAGE. S1, ;Ask the monitor
$STOP (CDW,<Can't determine working set error = ^O/S1/>)
MOVE S1,[POINT 1,BITMAP+1] ;Aim at the 512 bits
MOVSI S2,-^D512 ;Start at page 0
MOVX P1,PT.WRK ;Get our working set bit
MAPC.1: ILDB P2,S1 ;Get this page's bit
XCT [ANDCAM P1,PAGTBL(S2) ;Set or clear our bit
IORM P1,PAGTBL(S2)](P2) ;To match monitor's bit
AOBJN S2,MAPC.1 ;Do 'em all
$RETT
MAPLEN==<<^D512+^D35>/^D36>
$DATA (BITMAP,MAPLEN+1) ;Bit block, counted
>;END TOPS10
SUBTTL NODDT - Remove DDT.VMX routine for TOPS10
;This routine is intended to be used as an emergency tool
; in case a library gets saved with DDT in its high segment.
; In this case, any lowseg program which also has DDT.VMX in page 700
; will get page overlap errors when getting the library.
; It is not the intention that the library be saved in this state,
; however, if it happens, then this routine will be useful.
; The procedure is as follows:
; .GET GLXLIB ;The bad one, with DDT.VMX in it
; .DDT ;get into DDT.VMX
; NODDT$G ;Start it at this routine
; .SAVE ;Save the library without the symbols
TOPS10<
EXTERN .JBDDT
NODDT: SKIPN S1,.JBDDT ;Get the end,,start adr of DDT
JRST NODD.2 ;No DDT to begin with!
HRRZ T2,S1 ;Get start adr of DDT
HLRZ P1,S1 ;And ending adr
ADR2PG T2 ;Make starting page number
ADR2PG P1 ;Make ending page number
SUB P1,T2 ;Get number of pages in DDT
TXO T2,1B0 ;Light the destroy page bit
MOVEI T1,1 ;Count the args to PAGE. UUO
MOVE S2,[XWD .PAGCD,T1] ;Create/Destroy,, adr of arg list
NODD.1: PAGE. S2, ;Get rid of a page
JRST NODDFA ;Complain!
AOS T2 ;Bump to next page
SOJGE P1,NODD.1 ;And try the rest of the pages
SETZ S1, ;Store 0 in protected DDT loc
SETDDT S1, ;And tell the monitor
EXIT ;And go back to monitor
;Here is trying to destroy DDT, and it isn't here at all!
NODD.2: OUTSTR [ASCIZ/
% DDT not loaded
/] ;Inform the dumb user
EXIT ;And leave 'em alone
;Here if the PAGE. UUO fails
NODDFA: OUTSTR [ASCIZ/
?Can't destroy DDT page
/]
EXIT ;And die
>;End TOPS10
PFH%L:
END