;++ ; MACRO64$WHAMI.M64 ; ; © Digital Equipment Corporation 1992, 1993. All rights reserved. ; ; Restricted Rights: Use, duplication, or disclosure by the ; U.S. Government is subject to restrictions as set forth in ; subparagraph (c) (1) (ii) of DFARS 252.227-7013, or in ; FAR 52.227-19, or in FAR 52.227-14 Alt. III, as applicable. ; ; This software is proprietary to and embodies the confidential ; technology of Digital Equipment Corporation. Possession, use, or ; copying of this software and media is authorized only pursuant to ; a valid written license from Digital or an authorized sublicensor. ; ; This is a complete MACRO-64 program which uses the SYS$CMKRNL OpenVMS System ; Service to change to kernel mode and determine the processor number ; with the MFPR_WHAMI privileged PALcode instruction. This example is ; one of three installed with MACRO-64: ; ; MACRO64$HELLO.M64 - Simple Hello World program ; Demonstrates calling standard macros ; MACRO64$WHAMI.M64 - Program that displays WHAMI IPR (this program) ; Demonstrates system calls ; MACRO64$PI.M64 - Program that computes PI ; Demonstrates general programming with ; MACRO-64 along with optimization techniques ; ; Digital suggests you become familiar with the concepts illustrated in ; the simple, MACRO64$HELLO.M64 example before you attempt to understand ; this example or the MACRO64$PI.M64 example. ; ; ; When this program is executed from a process that has the CMKRNL privilege, ; the main routine, CHMK, calls SYS$CMKRNL (Change Mode to Kernel) which: ; ; o Allows the calling process to change its access mode to ; kernel ; ; o Executes another routine, WHAMI, which issues the privileged ; CALL_PAL MFPR_WHAMI instruction, and then ; ; o Returns to the access mode in effect before the SYS$CMKRNL call was issued ; ; Upon return to the main routine, CHMK, the DEC C Runtime Library routine, ; printf, is called to print out: ; ; o The value which was contained in the Who-Am-I Register when it was ; copied into the memory location WHAMI_IPR upon completion of executing ; CALL_PAL MFPR_WHAMI instruction in the routine WHAMI. ; ; o The status return value contained in R0 after execution of the ; routine SYS$CMKRNL. ; ; The DEC C Runtime library is available with the OpenVMS AXP (TM) Operating ; System, regardless of whether you have purchased and installed the DEC C ; compiler product. ; ; Additionally, the R0 status value which is a status result of the ; SYS$CMKRNL system service call is returned in R0 by the main routine, ; CHMK, to DCL. ; ; ; When this program is run from a process that does not have the CMKRNL ; privilege, the call to SYS$CMKRNL immediately returns an error status ; and the WHAMI routine is not executed. ; ; Thus, different results are printed out depending on the privileges of ; the executing process. If the executing process does not have ; the CMKRNL process privilege, the following is displayed : ; ; © Digital Equipment Corporation 1992, 1993. All rights reserved. ; WHAMI_IPR = FFFFFFFFFFFFFFFF SYS$CMKRNL status = 00000024 ; %SYSTEM-F-NOPRIV, no privilege for attempted operation ; ; Since the main program returns the failure status from SYS$CMKRNL ; in R0 to DCL, the system displays the message "%SYSTEM-F-NOPRIV, ; no privilege for attempted operation". Additionally, no new value ; is placed in the WHAMI_IPR memory location since the WHAMI routine ; does not execute. Thus you see the reserved processor number "-1" ; as the contents of WHAMI_IPR. ; ; If the executing process does have the CMKRNL privilege, the ; following is a sample of what might be displayed: ; ; © Digital Equipment Corporation 1992, 1993. All rights reserved. ; WHAMI_IPR = 0000000000000000 SYS$CMKRNL status = 00000001 ; ; ; To run this program on OpenVMS AXP (TM), use the following commands: ; ; $ macro/alpha_axp/object=whami sys$examples:macro64$whami ; $ link whami ; $ run whami ;-- ;+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ ; MODULE VARIABLE DATA ;--------------------------------------------------------------------------- ;++ ; This is the data section shared by the WHAMI and CHMK routines. ; ; The location WHAMI_IPR contains the value returned by ; the CALL_PAL MFPR_WHAMI instruction. CALL_PAL MFPR_WHAMI returns ; the processor number in R0. This location is initialized to -1 because ; -1 is a reserved processor number and should never be returned in R0 ; by the CALL_PAL MFPR_WHAMI instruction. If this location remains at -1, ; it means that the CALL_PAL MFPR_WHAMI instruction never ; executed, and the routine WHAMI did not update the contents ; of the memory location WHAMI_IPR. ;-- $data_section WHAMI_IPR: .quad -1 ; Reserved WHAMI value ;+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ ; LOCAL ROUTINES ;--------------------------------------------------------------------------- $routine WHAMI, data_section_pointer=true, local=true ;++ ; The WHAMI routine is the routine which is called in kernel mode ; by the system service routine SYS$CMKRNL. ; ; The WHAMI routine executes the privileged PALcode instruction ; CALL_PAL MFPR_WHAMI. Upon completion of this instruction, the ; value of the Who-Am-I internal processor register is returned in R0. ; The WHAMI routines then stores the Who-Am-I value in the WHAMI_IPR memory ; location with the "stq r0, WHAMI_IPR" instruction. ; ; The $ROUTINE macro invocation above defines a routine named WHAMI. ; WHAMI is, by default, declared to be a NULL procedure which executes in ; the context of its caller. The $ROUTINE macro defines, by default, ; a linkage-section psect named $LINK$, a code-section psect named ; $CODE$, and a data-section psect name $DATA$. The macro argument ; data_section_pointer is specified as true. This causes a pointer to ; the data-section psect to be placed WHAMI's linkage section. The local ; argument is also specified as true. This causes the WHAMI routine to ; be visible only within this module; a global symbol for WHAMI is not ; generated. The $ROUTINE macro leaves you in the code-section psect. ;-- .base r27, $ls ; Inform assembler that r27 --> linkage section ;++ ; When $ROUTINE defines the $DATA$ psect, it defines the $DS (data section) ; symbol as the current address in the $DATA$ psect. Because we specified ; data_section_pointer=true, $ROUTINE also stored that address in the linkage ; section using a .ADDRESS $DS directive. $ROUTINE also defines the $DP ; (data section pointer) symbol as the address of the data section pointer ; that is stored in the linkage section. Since we already have access to ; the linkage section via R27, we can therefore load from the linkage section ; the pointer to the data section into R22. ;-- ldq r22, $dp ; r22 --> data section .base r22, $ds ; Tell assembler that r22 --> data section ;++ ; Now we can execute the CALL_PAL MFPR_WHAMI instruction and store the ; Who-Am-I internal processor register in R0. Afterwards, we store the ; result in the WHAMI_IPR memory location in the data section. By virtue ; of the .BASE R22, $DS directive above, the assembler knows that R22 ; contains the base address of the data section. Therefore, it selects ; R22 as the base register for the target argument of the STQ instruction ; and computes the correct offset within the data section. ;-- call_pal mfpr_whami ; Issue the CALL_PAL instruction stq r0, WHAMI_IPR ; Update memory location WHAMI_IPR ; with the value contained in ; Who-Am-I Register. ;++ ; R0 is used to return a status value. '1' indicates success. ;-- mov 1, r0 ;++ ; The WHAMI routine can now return to its caller. Since WHAMI is a null- ; frame routine, it has no prologue or epilogue. Therefore, rather than ; invoking the $RETURN macro as you might with a stack or register-frame ; routine, we simply use the ret instruction. WHAMI's caller will have ; loaded R26 with the return address as part of the call sequence. ;-- ret r26 $end_routine WHAMI ;+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ ; EXTERNAL ROUTINES ;--------------------------------------------------------------------------- $routine CHMK, kind=stack, saved_regs=, - data_section_pointer=true ;++ ; CHMK is the main routine. ; ; The $ROUTINE macro invocation above defines a routine named CHMK. ; CHMK is a stack frame procedure that maintains its caller's context on ; the SP stack. It saves and restores R2 and R13 in addition to the ; frame pointer register (FP, or R29). The standard prologue generated by ; $ROUTINE saves these registers for us. ;- ;++ ; Following is routine CHMK's linkage section. It contains the ; strings, COPYRIGHT_MSG and WHAMI_MSG, both passed as arguments ; to the DEC C PRINTF routine, which prints out the value saved ; as the Who-Am-I Register value in the memory location WHAMI_IPR, ; and the status value returned after calling the system service ; routine SYS$CMKRNL to execute the routine WHAMI. ;-- $linkage_section COPYRIGHT_MSG: .asciz - ; \xA9 is '©', \x0A is , or '\n' in C parlance "\xA9 Digital Equipment Corporation 1992, 1993. All rights reserved.\x0A" MSG: .asciz "WHAMI_IPR = %08X%08X SYS$CMKRNL status = %08X\x0A" ;++ ; Following is the code section for the main routine CHMK. ;-- $code_section mov r27, r13 ; Save the procedure value in R13 .base r13, $ls ; Tell the assembler to use R13 as ; the base to the linkage section ; Output the copyright message. $call DECC$GPRINTF, args=COPYRIGHT_MSG/a ;++ ; Perform the system service call. Arguments are: ; o Routine WHAMI to be executed in the kernel mode ; o a terminating argument list element of 0. ;-- $call SYS$CMKRNL, args= mov r0, r2 ; Save SYS$CMKRNL's return status in R2 ;++ ; Access the data section in the same way as with the WHAMI routine. ;-- ldq r24, $dp .base r24, $ds ;++ ; CALL DECC$GPRINTF to output the values contained in ; WHAMI_IPR and R0. Arguments to the routine are: ; o The printf format string contained at MSG. ; o The value contained in the memory location WHAMI_IPR. ; o The value contained in R0. ; ; Additionally, registers R22 and R23 are specified as scratch registers ; to be used in the call. The default scratch registers are R0 and R1. ; In this case it is necessary to specify alternate scratch registers since ; R0 is used as an argument to DECC$GPRINTF. ;-- $call DECC$GPRINTF, - args=, - scratch_regs= ;++ ; Return in r0 the status value from the previous SYS$CMKRNL call that we ; saved ; previously in R2. ;-- mov r2, r0 ;++ ; Now we are ready to return. Unlike the WHAMI routine, CHMK is a stack ; routine and therefore requires an epilogue instruction sequence that ; restores the saved registers and performs necessary stack management. We ; use the $RETURN macro to generate that sequence. ;-- $return $end_routine CHMK .end CHMK ; Routine CHMK is the program entry point