.TITLE PAGE "Page management related routines" .IDENT /v1.0/ ;+ ; Facility: ; PAGE.MAR - Fool with memory ; ; Abstract: ; General utilities for manipulating VA ; ; Author: ; Bruce R. Miller, MILLER@TGV.COM ; TGV, Inc. ; 603 Mission St. ; Santa Cruz, CA 95060 ; (408) 427-4366 ; ; Date: ; 3-JUN-1991, late afternoon, on a beautiful sunny day, when I ; should be outside playing. ; ; Copyright (c) 1991 Bruce R. Miller ; All rights reserved. ; ; Redistribution and use in source and binary forms are permitted ; provided that the above copyright notice and this paragraph are ; duplicated in all such forms and that any documentation, ; advertising materials, and other materials related to such ; distribution and use acknowledge that the software was developed ; by Bruce R. Miller. ; THIS SOFTWARE IS PROVIDED AS IS'' AND WITHOUT ANY EXPRESS OR ; IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED ; WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. ; ; Modifications: ; ;- .link "sys$system:sys.stb"/SELECTIVE_SEARCH .library "sys$Library:lib.mlb" $DYNDEF $IPLDEF $IRPDEF $PCBDEF $PSLDEF $PTEDEF $SSDEF .entry MM_Krnl_AloNonPaged,^m ; Get a chunk of npagdyn MOVL @8(AP),R1 ; Get size JSB G^EXE$ALONONPAGED ; Get some non-paged pool BLBC R0,100$ ; If failed exit error ; Initialize it CLRQ (R2) ; Clear forward and back links MOVL R1,IRP$W_SIZE(R2) ; Set length field MOVL #DYN$C_NON_PAGED,IRP$B_TYPE(R2) ; Set type field ; leave MOVL R2,@4(AP) ; return address MOVL R1,@8(AP) ; return size MOVL #SS$_NORMAL,R0 ; success! 100$: RET .entry MM_AloNonPaged,^m MOVL AP,-(SP) MOVAB MM_Krnl_AloNonPaged,-(SP) CALLS #2,G^SYS$CMKRNL RET .entry MM_Krnl_DeaNonPaged,^m ; Check if current size is ok TSTL @8(AP) ; Size specified? BEQL 10$ ; br if not MOVL @8(AP),IRP$W_SIZE(R2) ; Set length field 10$: MOVZWL IRP$W_SIZE(R2),@8(AP) ; return size ; Throw it away MOVL 4(AP),R0 JSB G^EXE$DEANONPAGED ; Deallocate ; leave MOVL #SS$_NORMAL,R0 ; success! 100$: RET .entry MM_DeaNonPaged,^m MOVL AP,-(SP) MOVAB MM_Krnl_DeaNonPaged,-(SP) CALLS #2,G^SYS$CMKRNL RET ;++ ; Deposit_Krnl ; ; Input: ; 4(AP) - buffer address (in S0) ; 8(AP) - buffer size ; ; Note: ; First longword of buffer is target VA. ; Second longword of buffer # of bytes to transfer. ; The rest of the buffer is for the data transfer. ; ; Calling Context: ; IPL = 2 if special AST, otherwise 0 ; mode = kernel ; JSB Deposit_Krnl ;-- ADDR = 4 SIZE = 8 PID = 12 BUFF = 16 .entry Deposit_Krnl,^m ; Hey, how 'bout we add some flags, like /PID and /SPINLOCK? ; Check if IPL > 3? ; Get buffer address MOVL 4(AP),R3 ; set previous access mode to kernel ; MOVPSL -(SP) ; PSL ; PUSHAB 101$ ; PC ; MOVPSL -(SP) ; PSL ; PUSHAB 10$ ; PC ; INSV #0,#PSL$V_PRVMOD,#PSL$S_PRVMOD,4(SP) ; previous mode=kernel ; REI 10$: ; Read old value, if we can MOVL 4(AP),R3 PROBER #0,4(R3),@(R3) BEQL 110$ ; Save old value on the stack SUBL 4(R3),SP MOVL SP,R4 PUSHR #^m MOVC 4(R3),@(R3),(R4) POPR #^m ; Write new value, if we can (with SMP synchronization) PROBEW #0,4(R3),@(R3) BEQL 110$ INVALIDATE_TB ADDR=4(AP) ENVIRON=VMS - INST1=> - INST2= - INST3=> MOVL #SS$_NORMAL,R0 ; Move old value into the caller's buffer PUSHR #^m MOVC 4(R3),(R4),8(R3) POPR #^m ADDL 4(R3),SP 100$:; REI 101$: RET 110$: MOVL #SS$_ACCVIO,R0 BRB 100$ DEPOSIT_LENGTH = . - Deposit_Krnl ; We have to CMKRNL twice to setup the PSL prev acc field correctly for PROBE. ; It looks ugly, but it's the simplest way to check protection. ; Note: We could also do the old fake REI trick .entry Deposit2,^m<> MOVL AP,-(SP) MOVAB Deposit_Krnl,-(SP) CALLS #2,G^SYS$CMKRNL RET ;++ ; Deposit a value into a memory location (POKE) - ; ; Input: ; 4(AP) - Virtual address to modify ; 8(AP) - number of bytes to poke ; 12(AP) - PID of process to use as context (0 means current process) ; 16(AP) - address of buffer to hold values / store values in ; ; Output: ; R0 - status ; @16(AP) - bytes at location ;-- .entry Deposit,^m ; Set up buffer SUBL 8(AP),SP ; space for data MOVC 8(AP),@16(AP),(SP) ; copy the data PUSHL 8(AP) ; byte size PUSHL 4(AP) ; target VA MOVL SP,R2 ; buffer in R2 ADDL3 #8,SIZE(AP),R3 ; buffer size in R3 ;.BYTE ^xFD ; CLRL 0 ; Clear the event flag $CLREF_S EFN=#0 ; was a remote PID specified? TSTL 12(AP) BEQL 50$ ; Call Deposit_Krnl() in the context of process PID () PUSHL #0 ; EFN CLRQ -(SP) ; ASTADR and ASTPRM PUSHL R3 ; Data size PUSHL R2 ; Data ptr PUSHL #DEPOSIT_LENGTH ; Size of code PUSHAB Deposit_Krnl ; Code to execute PUSHL PID(AP) ; Our PID CALLS #8,CALL_REMOTE_G BLBC R0,100$ $WAITFR_S EFN=#0 ; wait for event flag. BRB 80$ 50$: ; do a local deposit PUSHL R3 PUSHL R2 PUSHL #2 PUSHL SP MOVAB Deposit2,-(SP) CALLS #2,G^SYS$CMKRNL 80$: ; Copy data into caller-provided buffer PUSHR #^m MOVC3 SIZE(AP),8(R2),@16(AP) POPR #^m 100$: RET ;++ ; Examine_Krnl ; ; Input: ; 4(AP) - buffer address (in S0) ; 8(AP) - buffer size ; ; Note: ; First longword of buffer is target VA. ; Second longword of buffer # of bytes to transfer. ; The rest of the buffer is for the data transfer. ; ; Calling Context: ; IPL = 2 if special AST, otherwise 0 ; mode = kernel ; JSB Examine_Krnl ;-- .entry Examine_Krnl,^m ; Check if IPL > 3? ; Get buffer address MOVL 4(AP),R0 ; Read value, if we can ; HACK!!! PROBER is no good! Use $PROBER macro. PROBER #0,4(R0),@(R0) BEQL 110$ PUSHR #^m MOVC3 4(R0),@(R0),8(R0) POPR #^m MOVL #SS$_NORMAL,R0 100$: RET 110$: MOVL #SS$_ACCVIO,R0 BRB 100$ EXAMINE_LENGTH = . - Examine_Krnl ; We have to CMKRNL twice to setup the PSL prev acc field correctly for PROBE. ; It looks ugly, but it's the simplest way to check protection. ; Note: We could also do the old fake REI trick .entry Examine2,^m<> MOVL AP,-(SP) MOVAB Examine_Krnl,-(SP) CALLS #2,G^SYS$CMKRNL RET ADDR = 4 SIZE = 8 PID = 12 BUFF = 16 ;++ ; Examine a memory location (PEEK) - ; ; Input: ; 4(AP) - Virtual address to examine ; 8(AP) - number of bytes to get ; 12(AP) - PID of process to use as context ; 16(AP) - address of buffer to store values in ; ; Output: ; R0 - status ; @16(AP) - bytes at location ;-- .ENTRY Examine,^M ; Set up buffer SUBL 8(AP),SP ; space for data PUSHL 8(AP) ; byte size PUSHL 4(AP) ; target VA MOVL SP,R2 ; buffer in R2 ADDL3 #8,SIZE(AP),R3 ; buffer size in R3 ; Clear the event flag $CLREF_S EFN=#0 ; was a remote PID specified? TSTL 12(AP) BEQL 50$ ; Call Examine_Krnl() in the context of process PID () PUSHL #0 ; EFN CLRQ -(SP) ; ASTADR and ASTPRM PUSHL R3 ; Data size PUSHL R2 ; Data ptr PUSHL #EXAMINE_LENGTH ; Size of code PUSHAB Examine_Krnl ; Code to execute PUSHL PID(AP) ; Our PID CALLS #8,CALL_REMOTE_G BLBC R0,100$ $WAITFR_S EFN=#0 ; wait for event flag. BRB 80$ 50$: ; do a local examine PUSHL R3 PUSHL R2 PUSHL #2 PUSHL SP MOVAB Examine2,-(SP) CALLS #2,G^SYS$CMKRNL 80$: ; Copy data into caller-provided buffer PUSHR #^m MOVC3 SIZE(AP),8(R2),@16(AP) POPR #^m 100$: RET ;++ ; ; Calling sequence: ; CALL #4,Set_Protection ; from kernel mode ; ; Input: ; 4(AP) - Starting VA ; 8(AP) - Length ; 12(AP) - Protection ; 16(AP) - Previous protection ; ; Output: ; R0 - Status ; R1 - Old protection, if R0 == sucess ;-- Locked_Pages: .LONG First_Locked_Page .LONG Last_Locked_Page First_Locked_Page: .entry Set_Protection,^m BBS #31,4(AP),100$ ; br if system VA ; Modify process page protection ADDL3 8(AP),4(AP),-(SP) ; Ending VA PUSHL 4(AP) ; Starting VA CLRL -(SP) PUSHL SP ; Previous protection addr PUSHL 12(AP) ; New prot: PUSHL #PSL$C_KERNEL ; access mode = kernel CLRL -(SP) ; no RETADR PUSHAL -8(FP) ; VA to change CALLS #5,G^SYS$SETPRT POPL R1 ; Put old prot in R1 RET 100$: ; This is high IPL code. Make sure we don't pagefault. $LKWSET_S Locked_Pages ; Bolt those suckers down BLBC R0,900$ MOVL 4(AP),R2 MOVL MMG$AR_SYSPCB,R4 MOVL MMG$GL_SYSPHD,R5 MFPR #PR$_IPL,R6 JSB MMG$PTEREF BLBC R0,900$ EXTZV #PTE$V_PROT,#PTE$S_PROT,- ; Get old prot from PTE (R3),R1 INSV 12(AP),#PTE$V_PROT,- ; Set prot in PTE #PTE$S_PROT,(R3) ;HACK!!! Replace next instruction with INVALIDATE_TB macro for SMP synchr. MTPR R2,#PR$_TBIS ; Invalidate translation buffer UNLOCK LOCKNAME=MMG,- ; Unlock the MMG database NEWIPL=R6,- PRESERVE=YES 900$: RET Last_Locked_Page: .entry Set_Page,^m<> MOVL AP,-(SP) MOVAB Set_Protection,-(SP) CALLS #2,G^SYS$CMKRNL TSTL 16(AP) BEQL 110$ MOVL R1,@16(AP) 110$: RET ;++ ; ; Calling sequence: ; CALL #2,Show_Protection ; from kernel mode ; ; Input: ; 4(AP) - Starting VA ; 8(AP) - Previous protection ; ; Output: ; R0 - Status ; R1 - Old protection, if R0 == sucess ;-- Locked_Pages2: .LONG First_Locked_Page2 .LONG Last_Locked_Page2 First_Locked_Page2: .entry Show_Protection,^m ; This is high IPL code. Make sure we don't pagefault. $LKWSET_S Locked_Pages2 ; Bolt those suckers down BLBC R0,100$ MOVL 4(AP),R2 BBS #31,R2,10$ ; br if system VA MOVL G^CTL$GL_PCB,R4 MOVL PCB$L_PHD(R4),R5 BRB 20$ 10$: MOVL G^MMG$AR_SYSPCB,R4 MOVL G^MMG$GL_SYSPHD,R5 20$: MFPR #PR$_IPL,R6 JSB G^MMG$PTEREF BLBC R0,100$ EXTZV #PTE$V_PROT,#PTE$S_PROT,- ; Get old prot from PTE (R3),R1 UNLOCK LOCKNAME=MMG,- ; Unlock the MMG database NEWIPL=R6,- PRESERVE=YES 100$: RET Last_Locked_Page2: .entry Show_Page,^m<> MOVL AP,-(SP) MOVAB Set_Protection,-(SP) CALLS #2,G^SYS$CMKRNL TSTL 8(AP) BEQL 110$ MOVL R1,@8(AP) 110$: RET .end