; 0001 0 ! ; 0002 0 %TITLE 'Convert virtual address to physical address' ; 0003 0 MODULE convert (IDENT = 'V001-1', ! File: CONVERT_VA.BLI ; 0004 0 MAIN = MAIN ; 0005 0 ) = ; 0006 1 BEGIN ; 0007 1 ; 0008 1 !++ ; 0009 1 ! ; 0010 1 ! FACILITY: DECUS pre-symposium seminar 'BLISS for Macro users' examples ; 0011 1 ! ; 0012 1 ! This routine will show the use of: ; 0013 1 ! ; 0014 1 ! Run-time library routines ; 0015 1 ! System services ; 0016 1 ! Conditional macro ; 0017 1 ! Keyword macro ; 0018 1 ! Simple macros ; 0019 1 ! Calling a routine in kernel mode ; 0020 1 ! BLOCK ; 0021 1 ! VECTOR ; 0022 1 ! BLOCKVECTOR ; 0023 1 ! ASCID ; 0024 1 ! ; 0025 1 ! ABSTRACT: This program will ask the user for the virtual address, in ; 0026 1 ! hexadecimal, and respond with the physical address that the ; 0027 1 ! virtual address maps to. ; 0028 1 ! ; 0029 1 ! The page that contains the virtual address will be first ; 0030 1 ! locked down (using SYS$LCKPAG), this will tell us whether the ; 0031 1 ! address is valid, as SYS$LCKPAG will return error status if ; 0032 1 ! it isn't, and it will keep the page in memory so the physical ; 0033 1 ! address that we return will have some meaning. ; 0034 1 ! ; 0035 1 ! NOTE: Since this main routine is run in user mode, the user will ; 0036 1 ! not have read access to most of system space, and will not ; 0037 1 ! be able to convert protected system space addresses. This ; 0038 1 ! is not a restriction of the convert routine, but of the ; 0039 1 ! main routine running in user mode. ; 0040 1 ! ; 0041 1 ! The address can be found simply by extracting the Virtual Page ; 0042 1 ! Number from the virtual address given, and using it as an index ; 0043 1 ! into the appropriate page table (P0, P1, or system), and retreiving ; 0044 1 ! the Page Frame Number. ; 0045 1 ! ; 0046 1 ! ; 0047 1 ! ENVIRONMENT: VAX/VMS, kernel mode ; 0048 1 ! ; 0049 1 ! AUTHOR: Brian K Catlin ; 0050 1 ! ; 0051 1 ! CREATED: 11-MAY-1988 ; 0052 1 ! ; 0053 1 ! MODIFICATION ; 0054 1 ! HISTORY: ; 0055 1 ! ; 0056 1 ! V001-1 BKC001 Brian K Catlin 11-MAY-1988 ; 0057 1 ! Original version ; 0058 1 ! ; 0059 1 !-- ; 0060 1 ; 0062 1 %SBTTL 'Declarations' ; 0063 1 ; 0064 1 !+ ; 0065 1 ! SWITCHES: ; 0066 1 !- ; 0067 1 ; 0068 1 SWITCHES ADDRESSING_MODE (EXTERNAL = GENERAL, NONEXTERNAL = WORD_RELATIVE); ; 0069 1 ; 0070 1 !+ ; 0071 1 ! LINKAGE/GLOBAL REGISTERS: ; 0072 1 !- ; 0073 1 ; 0074 1 ! None. ; 0075 1 ; 0076 1 !+ ; 0077 1 ! LINKAGES: ; 0078 1 !- ; 0079 1 ; 0080 1 ! None. ; 0081 1 ; 0082 1 !+ ; 0083 1 ! TABLE OF CONTENTS: ; 0084 1 !- ; 0085 1 ; 0086 1 FORWARD ROUTINE ; 0087 1 main, ! Main entry point ; 0088 1 get_phy_addr; ! Look up the physical address ; 0089 1 ; 0090 1 !+ ; 0091 1 ! INCLUDE FILES: ; 0092 1 !- ; 0093 1 ; 0094 1 LIBRARY 'SYS$LIBRARY:LIB'; ! VMS executive macros/symbols. ; 0095 1 ; 0096 1 !+ ; 0097 1 ! MACROS: ; 0098 1 !- ; 0099 1 ; 0100 1 MACRO ; M 0101 1 _match (key, item) [] = ; M 0102 1 ; M 0103 1 !+ ; M 0104 1 ! ; M 0105 1 ! FUNCTIONAL DESCRIPTION: ; M 0106 1 ! ; M 0107 1 ! This macro recursively matches a given KEY lexeme to each lexeme ; M 0108 1 ! in a lexeme list. If a match occurs then the macro expands to a ; M 0109 1 ! 1 (TRUE). If no match occurs then the macro expands to 0 (FALSE). ; M 0110 1 ! ; M 0111 1 ! By default, lexemes are converted to uppercase unless the caller ; M 0112 1 ! encloses each lexeme in quotes. ; M 0113 1 ! ; M 0114 1 ! FORMAL PARAMETERS: ; M 0115 1 ! ; M 0116 1 ! KEY Lexeme to be matched. ; M 0117 1 ! ITEM List of lexemes to match KEY against. ; M 0118 1 ! ; M 0119 1 ! COMPLETION VALUE: ; M 0120 1 ! ; M 0121 1 ! 0 No match was found. ; M 0122 1 ! 1 Match was found. ; M 0123 1 ! ; M 0124 1 !- ; M 0125 1 ; M 0126 1 !+ ; M 0127 1 ! If KEY is identical to the first argument of the argument list ; M 0128 1 ! then a match has been made. Expand to 1 (TRUE). ; M 0129 1 !- ; M 0130 1 ; M 0131 1 %IF %IDENTICAL (key, item) ; M 0132 1 %THEN ; M 0133 1 1 %EXITMACRO ; M 0134 1 %ELSE ; M 0135 1 ; M 0136 1 !+ ; M 0137 1 ! If there are no more arguments then no match was found. Exit ; M 0138 1 ! this recursive level with 0 (FALSE). This will be the expansion ; M 0139 1 ! of the entire recursive structure. ; M 0140 1 !- ; M 0141 1 ; M 0142 1 %IF %NULL (%REMAINING) ; M 0143 1 %THEN ; M 0144 1 0 %EXITMACRO ; M 0145 1 ; M 0146 1 !+ ; M 0147 1 ! If more arguments exist then recursively call _MATCH. ; M 0148 1 !- ; M 0149 1 ; M 0150 1 %ELSE ; M 0151 1 _match (key, %REMAINING) ; M 0152 1 %FI ; M 0153 1 ; M 0154 1 %FI ; M 0155 1 ; 0156 1 %; ; 0157 1 ; 0158 1 KEYWORDMACRO ; 0159 1 _string_desc ( ; 0160 1 class = s, ; 0161 1 dtype = t, ; 0162 1 length = 0, ; M 0163 1 pointer = 0 ) = ; M 0164 1 ; M 0165 1 !+ ; M 0166 1 ! ; M 0167 1 ! FUNCTIONAL DESCRIPTION: ; M 0168 1 ! ; M 0169 1 ! This macro initializes a string descriptor previously declared ; M 0170 1 ! using the PRESET attribute. ; M 0171 1 ! ; M 0172 1 ! The CLASS and DTYPE entries are checked to see if they correspond ; M 0173 1 ! to valid system defined string type codes. If not a compiler ; M 0174 1 ! warning message is given. Macro expansion continues assuming that ; M 0175 1 ! the caller has defined his own string type. ; M 0176 1 ! ; M 0177 1 ! LENGTH and POINTER fields are check to ensure that they are given ; M 0178 1 ! link-time-constant-expressions as actuals. If not, the an error ; M 0179 1 ! is issued, thus terminating all macro expansion. ; M 0180 1 ! ; M 0181 1 ! The default field specifiers define a null static string. ; M 0182 1 ! ; M 0183 1 ! A discussion of descriptors and their fields can be found in the ; M 0184 1 ! "VAX-11 ARCHITECTURE HANDBOOK" starting on page 409. ; M 0185 1 ! ; M 0186 1 ! FORMAL PARAMETERS: ; M 0187 1 ! ; M 0188 1 ! CLASS Single lexeme referring to a string descriptor ; M 0189 1 ! CLASS code. (Defaults to S) ; M 0190 1 ! DTYPE Single lexeme referring to a string descriptor ; M 0191 1 ! DATA TYPE field. (Defaults to T) ; M 0192 1 ! LENGTH Word expression used to initialize the descriptor ; M 0193 1 ! LENGTH field. (Defaults to 0) ; M 0194 1 ! POINTER Address expression used to initialize the descriptor ; M 0195 1 ! POINTER field. (defaults to 0) ; M 0196 1 ! ; M 0197 1 !- ; M 0198 1 ; M 0199 1 !+ ; M 0200 1 ! Declare the string descriptor as a block structure of the appropriate ; M 0201 1 ! size as specified by the CLASS code. ; M 0202 1 !- ; M 0203 1 ; M 0204 1 BLOCK [%NAME ('dsc$k_', class, '_bln'), BYTE] ; M 0205 1 ; M 0206 1 !+ ; M 0207 1 ! Preset the fields. ; M 0208 1 !- ; M 0209 1 ; M 0210 1 PRESET( ; M 0211 1 ; M 0212 1 !+ ; M 0213 1 ! If the CLASS or DTYPE fields do not correspond to system defined ; M 0214 1 ! codes then issue a WARNING. ; M 0215 1 !- ; M 0216 1 ; M 0217 1 %IF _match (class, s, d, vs) ; M 0218 1 %THEN ; M 0219 1 %ELSE ; M 0220 1 %WARN ('_STRING_DESC - ', class, ' not a system defined string', ' descriptor class') ; M 0221 1 %FI ; M 0222 1 ; M 0223 1 [dsc$b_class] = %NAME ('dsc$k_class_', class), ; M 0224 1 ; M 0225 1 %IF _match (dtype, t, nu, nl, nlo, nr, nro, nz, p) ; M 0226 1 %THEN ; M 0227 1 %ELSE ; M 0228 1 %WARN ('_STRING_DESC - ', dtype, ' not a system defined string', ' data type') ; M 0229 1 %FI ; M 0230 1 ; M 0231 1 [dsc$b_dtype] = %NAME ('dsc$k_dtype_', dtype), [dsc$w_length] = length, [dsc$a_pointer] = pointer) ; M 0232 1 ! Close off the PRESET. ; 0233 1 %; ; 0234 1 ; 0235 1 !+ ; 0236 1 ! FIELDS: ; 0237 1 !- ; 0238 1 ; 0239 1 ! None. ; 0240 1 ; 0241 1 !+ ; 0242 1 ! STRUCTURES: ; 0243 1 !- ; 0244 1 ; 0245 1 ! None. ; 0246 1 ; 0247 1 !+ ; 0248 1 ! PROGRAM SECTION DECLARATIONS: ; 0249 1 !- ; 0250 1 ; 0251 1 ! None. ; 0252 1 ; 0253 1 !+ ; 0254 1 ! EQUATED SYMBOLS: ; 0255 1 !- ; 0256 1 ; 0257 1 ! None. ; 0258 1 ; 0259 1 !+ ; 0260 1 ! OWN (R/O) STORAGE: ; 0261 1 !- ; 0262 1 ; 0263 1 ! None. ; 0264 1 ; 0265 1 !+ ; 0266 1 ! OWN (R/W) STORAGE: ; 0267 1 !- ; 0268 1 ; 0269 1 ! None. ; 0270 1 ; 0271 1 !+ ; 0272 1 ! BUILTIN DECLARATIONS: ; 0273 1 !- ; 0274 1 ; 0275 1 ! None. ; 0276 1 ; 0277 1 !+ ; 0278 1 ! EXTERNAL ROUTINES: ; 0279 1 ! ; 0280 1 ! OTS$CVT_TZ_L Convert a hexadecimal text string to a longword ; 0281 1 ! LIB$SYS_FAO Format an ASCII string, using dynamic strings ; 0282 1 ! LIB$GET_INPUT Get a string from the terminal ; 0283 1 ! LIB$PUT_OUTPUT Write a string to the terminal ; 0284 1 ! ; 0285 1 !- ; 0286 1 ; 0287 1 EXTERNAL ROUTINE ; 0288 1 ots$cvt_tz_l, ; 0289 1 lib$sys_fao, ; 0290 1 lib$get_input, ; 0291 1 lib$put_output; ; 0292 1 ; 0293 1 !+ ; 0294 1 ! EXTERNAL REFERENCES: ; 0295 1 !- ; 0296 1 ; 0297 1 EXTERNAL ; 0298 1 mmg$gl_sptbase, ! Address of the system page table ; 0299 1 sch$gl_curpcb : REF BLOCK [, BYTE]; ! Address of the PCB for the current process ; 0300 1 ; 0302 1 %SBTTL 'MAIN - Main entry point for this program' ; 0303 1 ROUTINE MAIN = ; 0304 1 ; 0305 1 !++ ; 0306 1 ! ; 0307 1 ! FUNCTIONAL DESCRIPTION: ; 0308 1 ! ; 0309 1 ! This routine will ask the user for the virtual address to be converted, ; 0310 1 ! create an argument block to pass this address to the convert routine ; 0311 1 ! (get_phy_addr), call the convert routine in kernel mode (requires CMKRNL ; 0312 1 ! privilege), and display the physical address on the user's terminal. The ; 0313 1 ! convert routine will return the physical address that the virtual address ; 0314 1 ! maps to. ; 0315 1 ! ; 0316 1 ! ENVIRONMENT: ; 0317 1 ! ; 0318 1 ! All access modes, AST reentrant. ; 0319 1 ! ; 0320 1 ! CALLING SEQUENCE: ; 0321 1 ! ; 0322 1 ! main () Called by VMS as the entry point of this program ; 0323 1 ! ; 0324 1 ! LINKAGE: ; 0325 1 ! ; 0326 1 ! CALL ; 0327 1 ! ; 0328 1 ! FORMAL PARAMETERS: ; 0329 1 ! ; 0330 1 ! None. ; 0331 1 ! ; 0332 1 ! IMPLICIT INPUTS: ; 0333 1 ! ; 0334 1 ! None. ; 0335 1 ! ; 0336 1 ! IMPLICIT OUTPUTS: ; 0337 1 ! ; 0338 1 ! None. ; 0339 1 ! ; 0340 1 ! COMPLETION CODES: ; 0341 1 ! ; 0342 1 ! SS$_NORMAL Normal successful completion. ; 0343 1 ! ; 0344 1 ! SIDE EFFECTS: ; 0345 1 ! ; 0346 1 ! Kernel mode call made to convert routine ; 0347 1 ! ; 0348 1 !-- ; 0349 1 ; 0350 2 BEGIN ; 0351 2 ; 0352 2 LOCAL ; 0353 2 lock_range : VECTOR [2, LONG], ! Range of addresses to lock down ; 0354 2 status : LONG, ! Generic status variable ; 0355 2 virtual_addr : LONG, ! Virtual address to convert ; 0356 2 descriptor : _string_desc (class = d), ! Generic string descriptor ; 0357 2 arg_block : VECTOR [3, LONG]; ! Argument block used by SYS$CMKRNL ; 0358 2 ; 0359 2 !+ ; 0360 2 ! Ask the user for the address to convert ; 0361 2 !- ; 0362 2 ; 0363 3 IF NOT (status = lib$get_input (descriptor, %ASCID'Virtual address in HEX ', descriptor [dsc$w_length])) ; 0364 2 THEN ; 0365 2 SIGNAL (.status); ; 0366 2 ; 0367 2 !+ ; 0368 2 ! Convert the address from hexadecimal text to a longword ; 0369 2 !- ; 0370 2 ; 0371 3 IF NOT (status = ots$cvt_tz_l (descriptor, virtual_addr)) ; 0372 2 THEN ; 0373 2 SIGNAL (.status); ; 0374 2 ; 0375 2 !+ ; 0376 2 ! Try and lock the page into memory. If this isn't a valid page, then ; 0377 2 ! SYS$LCKPAG will complain, so we'll signal the error and let the system ; 0378 2 ! tell the user about it ; 0379 2 !- ; 0380 2 ; 0381 2 lock_range [0] = .virtual_addr; ; 0382 2 lock_range [1] = .virtual_addr; ; 0383 2 ; 0384 3 IF NOT (status = $lckpag (inadr = lock_range)) ! Lock the page ; 0385 2 THEN ; 0386 2 SIGNAL (.status); ; 0387 2 ; 0388 2 !+ ; 0389 2 ! Create an argument block to pass the virtual address to the convert routine ; 0390 2 ! which will be called in KERNEL mode ; 0391 2 !- ; 0392 2 ; 0393 2 arg_block [0] = 1; ; 0394 2 arg_block [1] = .virtual_addr; ; 0395 2 arg_block [2] = 0; ; 0396 2 $cmkrnl (routin = get_phy_addr, arglst = arg_block [0]); ! Call the routine ; 0397 2 ; 0398 2 !+ ; 0399 2 ! Since this is just a demo program, the page containing the virtual ; 0400 2 ! address doesn't need to be locked down any longer ; 0401 2 !- ; 0402 2 ; 0403 3 IF NOT (status = $ulkpag (inadr = lock_range)) ! Unlock the page ; 0404 2 THEN ; 0405 2 SIGNAL (.status); ; 0406 2 ; 0407 2 !+ ; 0408 2 ! Format the output string. The convert routine will return the physical address ; 0409 2 ! in the second parameter of the argument block ; 0410 2 !- ; 0411 2 ; 0412 3 IF NOT (status = lib$sys_fao (%ASCID'Physical address = !XL', descriptor [dsc$w_length], descriptor, .arg_block [2])) ; 0413 2 THEN ; 0414 2 SIGNAL (.status); ; 0415 2 ; 0416 2 !+ ; 0417 2 ! Write the output string to the user's terminal ; 0418 2 !- ; 0419 2 ; 0420 3 IF NOT (status = lib$put_output (descriptor)) ; 0421 2 THEN ; 0422 2 SIGNAL (.status); ; 0423 2 ; 0424 2 ss$_normal ! Routine value ; 0425 1 END; ! End of routine main .TITLE CONVERT Convert virtual address to physical address .IDENT \V001-1\ .PSECT $PLIT$,NOWRT,NOEXE,2 P.AAB: .ASCII \Virtual address in HEX \<0> ; 20 6C 61 75 74 72 69 56 00000 ; 20 73 73 65 72 64 64 61 00008 ; 00 20 58 45 48 20 6E 69 00010 P.AAA: .LONG 17694743 ; 010E0017 00018 .ADDRESS P.AAB ; 00000000' 0001C P.AAD: .ASCII \Physical address = !XL\<0><0> ; 6C 61 63 69 73 79 68 50 00020 ; 73 73 65 72 64 64 61 20 00028 ; 00 00 4C 58 21 20 3D 20 00030 P.AAC: .LONG 17694742 ; 010E0016 00038 .ADDRESS P.AAD ; 00000000' 0003C .EXTRN OTS$CVT_TZ_L, LIB$SYS_FAO, LIB$GET_INPUT, LIB$PUT_OUTPUT, MMG$GL_SPTBASE, SCH$GL_CURPCB .EXTRN SYS$LCKPAG, SYS$CMKRNL, SYS$ULKPAG .PSECT $CODE$,NOWRT,2 ;MAIN U.1: .WORD ^M ;Save R2 0303 0004 00000 SUBL2 #32, SP ;#32, SP 5E 20 C2 00002 MOVL #34471936, 16(SP) ;#34471936, DESCRIPTOR 0356 10 AE 020E0000 8F D0 00005 CLRL 20(SP) ;DESCRIPTOR+4 14 AE D4 0000D PUSHAB 16(SP) ;DESCRIPTOR 0363 10 AE 9F 00010 PUSHAB W^P.AAA ;P.AAA 0000' CF 9F 00013 PUSHAB 24(SP) ;DESCRIPTOR 18 AE 9F 00017 CALLS #3, G^LIB$GET_INPUT ;#3, LIB$GET_INPUT 00000000G 00 03 FB 0001A MOVL R0, R2 ;R0, STATUS 52 50 D0 00021 BLBS R2, 1$ ;STATUS, 1$ 09 52 E8 00024 PUSHL R2 ;STATUS 0365 52 DD 00027 CALLS #1, G^LIB$SIGNAL ;#1, LIB$SIGNAL 00000000G 00 01 FB 00029 1$: PUSHL SP ;SP 0371 5E DD 00030 PUSHAB 20(SP) ;DESCRIPTOR 14 AE 9F 00032 CALLS #2, G^OTS$CVT_TZ_L ;#2, OTS$CVT_TZ_L 00000000G 00 02 FB 00035 MOVL R0, R2 ;R0, STATUS 52 50 D0 0003C BLBS R2, 2$ ;STATUS, 2$ 09 52 E8 0003F PUSHL R2 ;STATUS 0373 52 DD 00042 CALLS #1, G^LIB$SIGNAL ;#1, LIB$SIGNAL 00000000G 00 01 FB 00044 2$: MOVL (SP), 24(SP) ;VIRTUAL_ADDR, LOCK_RANGE 0381 18 AE 6E D0 0004B MOVL (SP), 28(SP) ;VIRTUAL_ADDR, LOCK_RANGE+4 0382 1C AE 6E D0 0004F CLRQ -(SP) ;-(SP) 0384 7E 7C 00053 PUSHAB 32(SP) ;LOCK_RANGE 20 AE 9F 00055 CALLS #3, G^SYS$LCKPAG ;#3, SYS$LCKPAG 00000000G 00 03 FB 00058 MOVL R0, R2 ;R0, STATUS 52 50 D0 0005F BLBS R2, 3$ ;STATUS, 3$ 09 52 E8 00062 PUSHL R2 ;STATUS 0386 52 DD 00065 CALLS #1, G^LIB$SIGNAL ;#1, LIB$SIGNAL 00000000G 00 01 FB 00067 3$: MOVL #1, 4(SP) ;#1, ARG_BLOCK 0393 04 AE 01 D0 0006E MOVL (SP), 8(SP) ;VIRTUAL_ADDR, ARG_BLOCK+4 0394 08 AE 6E D0 00072 CLRL 12(SP) ;ARG_BLOCK+8 0395 0C AE D4 00076 PUSHAB 4(SP) ;ARG_BLOCK 0396 04 AE 9F 00079 PUSHAB W^U.2 ;U.2 0000V CF 9F 0007C CALLS #2, G^SYS$CMKRNL ;#2, SYS$CMKRNL 00000000G 00 02 FB 00080 CLRQ -(SP) ;-(SP) 0403 7E 7C 00087 PUSHAB 32(SP) ;LOCK_RANGE 20 AE 9F 00089 CALLS #3, G^SYS$ULKPAG ;#3, SYS$ULKPAG 00000000G 00 03 FB 0008C MOVL R0, R2 ;R0, STATUS 52 50 D0 00093 BLBS R2, 4$ ;STATUS, 4$ 09 52 E8 00096 PUSHL R2 ;STATUS 0405 52 DD 00099 CALLS #1, G^LIB$SIGNAL ;#1, LIB$SIGNAL 00000000G 00 01 FB 0009B 4$: PUSHL 12(SP) ;ARG_BLOCK+8 0412 0C AE DD 000A2 PUSHAB 20(SP) ;DESCRIPTOR 14 AE 9F 000A5 PUSHAB 24(SP) ;DESCRIPTOR 18 AE 9F 000A8 PUSHAB W^P.AAC ;P.AAC 0000' CF 9F 000AB CALLS #4, G^LIB$SYS_FAO ;#4, LIB$SYS_FAO 00000000G 00 04 FB 000AF MOVL R0, R2 ;R0, STATUS 52 50 D0 000B6 BLBS R2, 5$ ;STATUS, 5$ 09 52 E8 000B9 PUSHL R2 ;STATUS 0414 52 DD 000BC CALLS #1, G^LIB$SIGNAL ;#1, LIB$SIGNAL 00000000G 00 01 FB 000BE 5$: PUSHAB 16(SP) ;DESCRIPTOR 0420 10 AE 9F 000C5 CALLS #1, G^LIB$PUT_OUTPUT ;#1, LIB$PUT_OUTPUT 00000000G 00 01 FB 000C8 MOVL R0, R2 ;R0, STATUS 52 50 D0 000CF BLBS R2, 6$ ;STATUS, 6$ 09 52 E8 000D2 PUSHL R2 ;STATUS 0422 52 DD 000D5 CALLS #1, G^LIB$SIGNAL ;#1, LIB$SIGNAL 00000000G 00 01 FB 000D7 6$: MOVL #1, R0 ;#1, R0 0425 50 01 D0 000DE RET ; 04 000E1 ; Routine Size: 226 bytes, Routine Base: $CODE$ + 0000 ; 0427 1 %SBTTL 'GET_PHY_ADDR - Look up the passed virtual address, and pass back its physical address' ; 0428 1 ROUTINE get_phy_addr (v_addr, p_addr) = ; 0429 1 ; 0430 1 !++ ; 0431 1 ! ; 0432 1 ! FUNCTIONAL DESCRIPTION: ; 0433 1 ! ; 0434 1 ! This routine will look up the corresponding physical address for ; 0435 1 ! a given virtual address. This is done by extracting the Virtual ; 0436 1 ! Page Number (VPN) from the virtual address (bits 10 through 31), ; 0437 1 ! and using this as an index into the appropriate page table (P0, ; 0438 1 ! P1, or system, selected by looking at bits 30 and 31), and ; 0439 1 ! returning the Page Frame Number (PFN) for that page. ; 0440 1 ! ; 0441 1 ! NOTE: This routine assumes that the given virtual address is ; 0442 1 ! within range, and in memory, so no checking is done as ; 0443 1 ! to whether this a valid page ; 0444 1 ! ; 0445 1 ! ENVIRONMENT: ; 0446 1 ! ; 0447 1 ! Kernel access mode ; 0448 1 ! ; 0449 1 ! CALLING SEQUENCE: ; 0450 1 ! ; 0451 1 ! get_phy_addr (v_addr, p_addr) ; 0452 1 ! ; 0453 1 ! LINKAGE: ; 0454 1 ! ; 0455 1 ! CALL ; 0456 1 ! ; 0457 1 ! FORMAL PARAMETERS: ; 0458 1 ! ; 0459 1 ! v_addr Virtual address to convert ; 0460 1 ! p_addr Physical address of passed virtual address ; 0461 1 ! ; 0462 1 ! IMPLICIT INPUTS: ; 0463 1 ! ; 0464 1 ! None. ; 0465 1 ! ; 0466 1 ! IMPLICIT OUTPUTS: ; 0467 1 ! ; 0468 1 ! None. ; 0469 1 ! ; 0470 1 ! COMPLETION CODES: ; 0471 1 ! ; 0472 1 ! SS$_NORMAL Normal successful completion. ; 0473 1 ! ; 0474 1 ! SIDE EFFECTS: ; 0475 1 ! ; 0476 1 ! None. ; 0477 1 ! ; 0478 1 !-- ; 0479 1 ; 0480 2 BEGIN ; 0481 2 ; 0482 2 MAP ; 0483 2 v_addr : BLOCK [, BYTE]; ! Make the v_addr look like a block so we ; 0484 2 ; 0485 2 ! can reference bit fields within it ; 0486 2 ; 0487 2 LOCAL ; 0488 2 page_table : REF BLOCKVECTOR [, pte$s_ptedef, BYTE]; ; 0489 2 ; 0490 2 !+ ; 0491 2 ! Determine which page table to use. If bit 31 (va$v_system) is set, then this ; 0492 2 ! is a system space (above 80000000) address ; 0493 2 !- ; 0494 2 ; 0495 2 IF .v_addr [va$v_system] ; 0496 2 THEN ; 0497 2 page_table = .mmg$gl_sptbase ! Use the system page table ; 0498 2 ELSE ; 0499 2 ; 0500 2 !+ ; 0501 2 ! Since this isn't a system space address, we now have to decide which ; 0502 2 ! process page table to use, P0, or P1. If bit 30 (va$v_p1) is set, then ; 0503 2 ! this is a P1 space (40000000 to 7fffffff) address, otherwise it is a ; 0504 2 ! P0 space (00000000 to 3fffffff) address ; 0505 2 !- ; 0506 2 ; 0507 3 BEGIN ; 0508 3 ; 0509 3 LOCAL ; 0510 3 proc_hdr : REF BLOCK [, BYTE]; ; 0511 3 ; 0512 3 proc_hdr = .sch$gl_curpcb [pcb$l_phd]; ! Get the address of our process header ; 0513 3 ; 0514 3 IF .v_addr [va$v_p1] ; 0515 3 THEN ; 0516 3 page_table = .proc_hdr [phd$l_p1br] ! Use process P1 page table ; 0517 3 ELSE ; 0518 3 page_table = .proc_hdr [phd$l_p0br]; ! Use process P0 page table ; 0519 3 ; 0520 2 END; ; 0521 2 ; 0522 2 !+ ; 0523 2 ! Now that we have the correct page table, look up the address of the page ; 0524 2 ! that the virtual page is mapped to, and then add in the offset within that ; 0525 2 ! page (va$v_byte) so we get the address of the byte the user is requesting ; 0526 2 !- ; 0527 2 ; 0528 2 p_addr = (.page_table [.v_addr [va$v_vpn], pte$v_pfn]^va$s_byte) + .v_addr [va$v_byte]; ; 0529 2 ! ; 0530 2 ss$_normal ! Routine value ; 0531 1 END; ! End of routine get_phy_addr ;GET_PHY_ADDR U.2: .WORD ^M<> ;Save nothing 0428 0000 00000 TSTB 7(AP) ;V_ADDR+3 0495 07 AC 95 00002 BGEQ 1$ ;1$ 09 18 00005 MOVL G^MMG$GL_SPTBASE, R0 ;MMG$GL_SPTBASE, PAGE_TABLE 0497 50 00000000G 00 D0 00007 BRB 3$ ;3$ 1C 11 0000E 1$: MOVL G^SCH$GL_CURPCB, R1 ;SCH$GL_CURPCB, R1 0512 51 00000000G 00 D0 00010 MOVL 108(R1), R1 ;108(R1), PROC_HDR 51 6C A1 D0 00017 BBC #6, 7(AP), 2$ ;#6, V_ADDR+3, 2$ 0514 07 AC 06 E1 0001B ; 07 0001F MOVL 208(R1), R0 ;208(PROC_HDR), PAGE_TABLE 0516 50 00D0 C1 D0 00020 BRB 3$ ;3$ 05 11 00025 2$: MOVL 200(R1), R0 ;200(PROC_HDR), PAGE_TABLE 0518 50 00C8 C1 D0 00027 3$: EXTZV #1, #21, 5(AP), R1 ;#1, #21, V_ADDR+1, R1 0528 15 01 EF 0002C ; 51 05 AC 0002F PUSHAL (R0)[R1] ;(PAGE_TABLE)[R1] 6041 DF 00032 EXTZV #0, #21, @(SP)+, R0 ;#0, #21, @(SP)+, R0 15 00 EF 00035 ; 50 9E 00038 ASHL #9, R0, R0 ;#9, R0, R0 50 09 78 0003A ; 50 0003D EXTZV #0, #9, 4(AP), R1 ;#0, #9, V_ADDR, R1 09 00 EF 0003E ; 51 04 AC 00041 ADDL3 R1, R0, 8(AP) ;R1, R0, P_ADDR 50 51 C1 00044 ; 08 AC 00047 MOVL #1, R0 ;#1, R0 0531 50 01 D0 00049 RET ; 04 0004C ; Routine Size: 77 bytes, Routine Base: $CODE$ + 00E2 ; 0532 1 END ! End of module convert ; 0533 1 ; 0534 0 ELUDOM .EXTRN LIB$SIGNAL ; PSECT SUMMARY ; ; Name Bytes Attributes ; ; $PLIT$ 64 NOVEC,NOWRT, RD ,NOEXE,NOSHR, LCL, REL, CON,NOPIC,ALIGN(2) ; $CODE$ 303 NOVEC,NOWRT, RD , EXE,NOSHR, LCL, REL, CON,NOPIC,ALIGN(2) ; Library Statistics ; ; -------- Symbols -------- Pages Processing ; File Total Loaded Percent Mapped Time ; ; SYS$SYSROOT:[SYSLIB]LIB.L32;6 21522 23 0 1156 00:02.2 ; COMMAND QUALIFIERS ; BLISS/LIS=CONVERT_VA.MAR/SOU=NOHEAD/MACH=(ASS,UNI)/OPT=(SPEED,LEV=3) CONVERT_VA/NOOBJ ; Compilation Complete .END U.1