SVC Routines – Introduction

We can now explore how to add system level functionality using SVC (Supervisor Call) routines.  SVC routines are invoked through the use of the SVC machine instruction.  A SVC instruction causes a SVC Interruption to occur.  It effectively allows for a special type of call instruction that can switch between problem mode execution and supervisor mode.  SVC routines are defined at SYSGEN time.  SVC routines are categorized into six types.  Type 1, 2, and 6 SVC routines are linked as part of the resident control program.  Type 3 and 4 SVC routines reside in the Link Pack Area (LPA) and may be either fixed or pageable.  All SVC routines must be reentrant.  I will focus on type 3/4 SVC routines since they reside in LPA as individual modules and are less restrictive – and they provide all the functionality I am looking for.

SVC modules must have a specific name in the format:

Type 1, 2,  6 IGCnnn nnn = Signed Decimal Number
Type 3 IGC00nnn
Type 4 IGCssnnn ss = load module number -1

There are a maximum of 256 SVC routines that can be defined (0-255).  The nnn part of the name indicates the SVC number.  It is a signed decimal number so the last digit contains the sign in the high order four bits (x’C0′)  make the last digit a letter (A-I) for the numbers zero through nine.  If the last digit is zero then the last character is X’C0′ or ‘{‘.  For example a Type 3 SVC with the number 123 would be named “IGC0012C”.  If it was SVC 130 it would be named “IGC0013{“.  Once you understand the way the names are generated it is easy to deal with.  The difference between Type 3 and 4 SVC routines is that Type 3 routines consist of a singe module and type 4 routines are made up multiple modules.  For our purposes Type 3 and 4 SVC routines are the same.  A Type 5 SVC is a placeholder and indicates the SVC will be added after the SYSGEN in complete.

Since the SVC call is routed through the SVC interrupt handler the SVC routine does not have to save the callers registers (they are saved by the system in the Request Block).  Registers 0, 1, 13, and 15 are passed from the caller to the SVC routine.  On return the system restores registers 2 through 12.  The SVC routine may pass information back to the caller in registers 0, 1, and 15.  Register 13 usually points to a save area established by the calling routine.  It may be necessary for the SVC routine to establish a save area if standard call linkage will be used to call other routines.  Registers 3 through 7 contain parameters passed by the SVC interrupt handler.  Here is a summary of register contents on entry to a SVC routine:

 0  Same as when SVC was issued
 1  Same as when SVC was issued
 2  Unpredictable
 3  A(CVT)
 4  A(TCB)
 5  A(SVRB) Type 2,3,4
 6  Entry Point of SVC Routine
 7  A(ASCB)
 8  Unpredictable
 9  Unpredictable
10  Unpredictable
11  Unpredictable
12  Unpredictable
13  Same as when SVC was issued
14  Return Address
15  Same as when SVC was issued

A Simple SVC Routine

Now we can write a simple SVC routine.  We will accept two input parameters in registers 0 and 1.  The SVC routine will add the contents of these two registers and return the result in register 15.  This is really a very silly SVC routine but it will prove that we understand the basics of writing our own SVC.

On my system I happen to know that SVC number 230 is a Type 3 SVC and it is currently not in use.  I will use it for my test SVC routine but you may have to use another SVC number depending how SVC routines are defined and used on your system.

SVC01    CSECT ,        
         USING SVC01,R6 
*                       
         LR    R15,R0   
         AR    R15,R1   
*                       
         BR    R14

Here is our whole SVC routine (minus the equates for the registers).  Our load module must be named to reflect the SVC number (“IGC0023A” for SVC 231) but the internal CSECT name can be anything we want.  We establish addressability using register 6 as our base register since it already contains the entry point address.  We copy the value of register 0 into register 15 and then add teh value of register 1.  All that is left is to return using the address in register 14.  The contents of registers 0, 1, and 15 will be returned to the caller.

Now we can assemble and link into SYS1.LPALIB.

Next we need a test program to invoke our new SVC.  Here is the main part of the test program:

         LA    R0,111                     
         LA    R1,222                     
         SVC   231                        
*                                         
         CVD   R15,DOUBLE                 
         MVC   RESULT,=X'4020202020202120'
         ED    RESULT,DOUBLE+4            
*                                         
         MVC   WTO+8(8),RESULT            
WTO      WTO   '++++++++',ROUTCDE=(1,11)

I left out the program linkage but once our program is up and running we load up our two input parameter registers and issue the SVC instruction to call our SVC routine.  On return from the SVC we convert the return value in register 15 to decimal and use the edit instruction to make it printable.  The result is moved into the WTO parameter list and a message is sent to the console.

JOB 6815  $HASP373 SVC01T   STARTED - INIT 12 - CLASS A - SYS TCS3 
JOB 6815  IEF450I SVC01T MVSSP - ABEND SFE7 U0000 - TIME=07.06.47  
JOB 6815   7.06.48   0.00.00   0.00.00  SFE7   SVC01T    MVSSP     
JOB 6815   7.06.48   0.00.00   0.00.00  SFE7   SVC01T    ########  
JOB 6815  $HASP395 SVC01T   ENDED

When we try running our test program we get a System ABEND FE7.  Notice that X’E7′ is 231 decimal which is our SVC number.  This ABEND indicates the SVC has not been installed.  To actually get our SVC routine installed we need to IPL and CLPA (Create Link Pack Area) or we could use MLPA (Modify Link Pack Area) to do a temporary install of our routine.  A normal IPL does not change the LPA.  It is only rebuilt when CLPA is specified.

Now after a quick IPL with a CLPA we run our test again:

JOB 6825  $HASP373 SVC01T   STARTED - INIT 12 - CLASS A - SYS TCS3 
JOB 6825  +     333                                                
JOB 6825   7.31.17   0.00.00   0.00.00  0000   SVC01T    MVSSP     
JOB 6825   7.31.17   0.00.00   0.00.00  0000   SVC01T    ########  
JOB 6825  $HASP395 SVC01T   ENDED

And we get the expected result (111+222=333) which proves we have successfully written, installed, and invoked a SVC routine.

SVC Screening

SVC screening provides a way of screening (or intercepting) SVC calls at the task level.  A SVC screen table is created and the address is placed in a TCB.  Any SVC calls from that task that are marked for screening will be intercepted.  Control is passed to the screen routine from the SVC interrupt handler in exactly the same way SVC routines are invoked.

There are several implications of SVC screening.  First we can easily test new SVC code without the need to IPL and perfrom a CLPA or MLPA.  Also the SVC code is only active for tasks were the screening is activated.  With SVC screening we can test a new SVC routine or replace an existing SVC routine.  This applies to both user and system SVC routines.  It also provides a method to front-end SVC calls.

There are two fields in the TCB related to SVC screening.  TCBSVCS is a bit in the TCBFLGS7 field that indicates SVC screening is active if set to one or inactive if set to zero.  TCBSVCA2 is the pointer to the SVC screen table.  The screen table is 264 bytes long.  The first four bytes are the address of the SVC intercept routine that receives control when a screened SVC is invoked by the task.  The next four bytes  are flags that indicate the attributes of the SVC routine.  The first flag byte indicates the SVC type (X’00’ – Type 1, X’80’ – Type 1, X’C0′ – Type 3/4)  The second flag byte is not used and should be binary zeros.  The third and fourth flag bytes indicate the locks to be obtained before passing control to the SVC routine.  Binary zeros indicate no locks are to be obtained.  The next 256 bytes indicate which SVC numbers should be intercepted.  Each byte is a flag for a SVC number.  If the byte is set to X’80’ then the SVC is not to be intercepted.  If they byte is set to X’00’ then the SVC should be intercepted.   The SVC type and locks flags apply to all intercepted SVC numbers.

We now have enough information to write some code to test SVC screening.

SVC02    CSECT ,                                         
         SAVE  (14,12),,SVC02     SAVE CALLERS REGISTERS 
*                                                        
         LR    R12,R15            ESTABLISH              
         USING SVC02,R12                   BASE REGISTER 
*                                                        
         LA    R1,SAVEA           CHAIN                  
         ST    R1,8(,R13)              NEW               
         ST    R13,4(,R1)                 SAVE           
         LR    R13,R1                         AREA       
*

We start with our standard program linkage.

         LA    R1,=C'AUTH'        GET APF AUTHORIZATION    
         SVC   245                                         
*                                                          
         MODESET MODE=SUP         GET INTO SUPERVISOR MODE 
*                                                          
         LA    R1,0               RESET APF AUTHORIZATION  
         SVC   245

Next we obtain APF authorization using the SVC I have installed on my system for testing. You could also run from an APF authorized library. Once APF authorized the MODESET macro is used to swap into supervisor mode and then I clear the APF authorization. This is not really necessary and it shouldnt be necessary to reset it.

         IPK   ,                  GET PSW PROTECT KEY 
         LR    R11,R2             SAVE PK IN R11      
*                                                     
         SPKA  0                  GET INTO KEY ZERO

Next I save the current protect key from the PSW using the IPK instruction. The protect key is placed into register 2 so I copy it to register 11 to save it. I then use the SPKA instruction to get into protect key zero.

         GETMAIN R,LV=264,SP=253

Now we getmain some stroage for our SVC screen table. I use subpool 253 which is Fixed LSQA. This storage is task related and will automaticaly be freed when the task terminates. The storage is not fetch protected and is in key zero.

         LR    R3,R1              SAVE STORAGE ADDRESS         
         XC    0(8,R3),0(R3)      CLEAR FIRST 8 BYTES          
         LA    R1,SVCINT          ADDRESS OF SVC INTERCEPT RTN 
         ST    R1,0(,R3)          SAVE INTO PARMAMETER BLOCK   
         MVI   4(R3),X'C0'        INDICATE TYPE 3/4 SVC

The address of the LSQA storage is copied into register 3 and the first 8 bytes are zeroed out. The address of the routine to receive control from the SVC interrupt handler is placed in the first four bytes. The first flag byte is set to X’C0′ to indicate a Type 3/4 SVC. The lock flags are zero indicating no locks should be obtained.

         LA    R2,8(,R3)          POINT TO 256 BYTE SVC LIST    
         LA    R1,256                                           
INITLOOP DS    0H                                               
         MVI   0(R2),X'80'        INITIALIZE TO DO NOT INTERCEPT
         LA    R2,1(,R2)          NEXT BYTE                     
         BCT   R1,INITLOOP        LOOP BACK

Now we initialize the 256 byte list. Each byte in the list represents one SVC number. The first byte is for SVC 0, the next for SVC 1 and so on. We set each to a value of X’80’ so the SVC is not intercepted.

 *                                                           
          LA    R2,8(,R3)          POINT TO 256 BYTE SVC LIST
          MVI   230(R2),X'00'      INTERCEPT SVC 230         
 *

Now we indicate which SVC requests should be intercepted by setting the corresponding byte to X’00’. I chose to use SVC 230 because it is currently unused on my system. I does not matter how the SVC is defined in the SYSGEN since it is ignored for SVC screening.  Caution should be used to not accidently intercept a SVC that is currently in use on your system.

*                                                                    
         L     R2,16              CVT                                
         L     R2,0(,R2)          OLD/NEW POINTER                    
         L     R2,4(,R2)          TCB ADDRESS                        
         USING TCB,R2                                                
*                                                                    
         ST    R3,TCBSVCA2        STORE SCREEN TABLE ADDRESS INTO TCB
         OI    TCBFLGS7,TCBSVCS   TURN ON SVC SCREENING

Now we locate the address of our current TCB and store the address of the screen table into the TCBSVCA2 field.  Next we set the TCBSVCS bit to activate screening.

         SPKA  0(R11)             RESTORE PROTECT KEY                
*                                                                    
         SVC   230                SHOULD BE CAPTURED BY SVC SCREENING

Now we can restore our PSW protect key.  It is always a good idea to only operate in key zero only when necessary.  Now we issue SVC 230 to test our SVC screening intercept.

         L     R13,4(,R13)        UNCHAIN SAVE AREA         
         LM    R14,R12,12(R13)    RESTORE CALLERS REGISTERS 
         SLR   R15,R15            ZERO RC                   
         BR    R14                RETURN TO CALLER

Now we can exit back to the caller.

SVCINT   DS    0H                                            
         USING SVCINT,R6          SET BASE REGISTER          
*                                                            
         LR    R11,R14            SAVE RETURN ADDRESS        
*                                                            
         WTO   'HELLO FROM SVC SCREEN ROUTINE',ROUTCDE=(1,11)
*                                                            
         LR    R14,R11            RESTORE RETURN ADDRESS     
         BR    R14                EXIT SVC ROUTINE

Here is our SVC intercept routine.  The register contents are standard for a SVC routine.  We use register 6 as our base register.  The return address is saved in register 11.  All our SVC routine does is issue a WTO to write a message to the console.  Since we defined our SVC intercept as a Type 3/4 our SVC routine can issue SVC calls.  We then exit back to our caller.

SAVEA    DS    18F                REGISTER SAVE AREA
*                                                   
         LTORG ,                                    
*                                                   
         PRINT NOGEN                                
         IKJTCB DSECT=YES,LIST=NO                   
*                  
R0       EQU   0   
R1       EQU   1   
R2       EQU   2   
R3       EQU   3   
R4       EQU   4   
R5       EQU   5   
R6       EQU   6   
R7       EQU   7   
R8       EQU   8   
R9       EQU   9   
R10      EQU   10  
R11      EQU   11  
R12      EQU   12  
R13      EQU   13  
R14      EQU   14  
R15      EQU   15  
*                  
         END    ,

We finish up with our data areas and register equates.

JOB 6828  $HASP373 SVC02    STARTED - INIT 12 - CLASS A - SYS TCS3 
JOB 6828  HELLO FROM SVC SCREEN ROUTINE                            
JOB 6828   9.21.07   0.00.00   0.00.00  0000   SVC02     MVSSP     
JOB 6828   9.21.07   0.00.00   0.00.00  0000   SVC02     ########  
JOB 6828  $HASP395 SVC02    ENDED

Now we can assemble, link edit, and execute and we get our message. We have successfully intercepted SVC 230.

*        OI    TCBFLGS7,TCBSVCS   TURN ON SVC SCREENING

Just to prove that we are really intercepting a SVC call I commented out the line that sets the TCBSVCS bit so that SVC screening is not active.  Upon assembling, link editing, and executing we get:

JOB 6831  $HASP100 SVC02    ON INTRDR      RUN TEST PGM           
JOB 6831  $HASP373 SVC02    STARTED - INIT 12 - CLASS A - SYS TCS3
JOB 6831  IEF450I SVC02 MVSSP - ABEND SFE6 U0000 - TIME=08.23.57  
JOB 6831   8.23.57   0.00.00   0.00.00  SFE6   SVC02     MVSSP    
JOB 6831   8.23.57   0.00.00   0.00.00  SFE6   SVC02     ######## 
JOB 6831  $HASP395 SVC02    ENDED

A System ABEND FE6 indicates that SVC X’F6′ (230 decimal) was called but the SVC routine is not installed.

Screening Multiple SVC Calls

We have successfully managed to use SVC screening to intercept a SVC call.  The only problem is we can only specify one routine to receive control for the intercepted SVC(s).  What if we want to intercept more than one and execute specific code for each unique SVC call?  We have to add some logic to determine what SVC number was called.  Fortunately this information is saved in a Request Block.  When our SVC intercept routine is entered register 5 contains the address of the Supervisor Request Block (SVRB) that was created by the SVC interrupt handler.  This SVRB does not contain information about the SVC call but does point to the previous RB that does contain the system status that was saved when the SVC instruction caused an interrupt. By examining the previous RB we can determine the SVC number assoicated with the call to our intercept routine.

         USING RBBASIC,R5         MAP THE SVRB                     
*                                                                  
         L     R9,RBLINK          LINK TO PREVIOUS RB              
         LA    R9,0(,R9)          CLEAN UP ADDRESS                 
         BCTR  R9,0               BACK UP TO LAST BYTE OF RB PREFIX

Since register 5 contains the address of the SVRB we can use it to find the previous RB.  First we map it against the RBBASIC section of the Request Block.  We use the RBLINK field to get the address of the previous RB.  I use the LA instruction to “clean up” the address, that is to clear the high order bits of the address.  We then subtract one from that address so register 9 will point to the last byte of the prefix section of the RB that is located right before the beginning of the RBBASIC section.  The last byte of the RB prefix contains the SVC interruption code or SVC number.

          CLI   0(R9),230                                       
          BE    SVC230                                          
 *                                                              
          CLI   0(R9),231                                       
          BE    SVC231                                          
 *                                                              
          WTO   '*** NOT SVC 230 OR SVC 231 ***',ROUTCDE=(1,11)

Now we can simply use a CLI instruction to check the SVC number and branch to the appropriate processing routine. We should have some type of error code in place in the event the SVC number fails to match (because we made some type of coding error). Here we simply issue a WTO and then exit.

SVC230   DS    0H                                        
         WTO   '++++++++ SVC 230 ++++++++',ROUTCDE=(1,11)
*                                                        
         LR    R14,R11            RESTORE RETURN ADDRESS 
         BR    R14                EXIT SVC ROUTINE       
*                                                        
SVC231   DS    0H                                        
         WTO   '++++++++ SVC 231 ++++++++',ROUTCDE=(1,11)
*                                                        
         LR    R14,R11            RESTORE RETURN ADDRESS 
         BR    R14                EXIT SVC ROUTINE

Our SVC routines aren’t much more interesting but they will reveal which SVC number was called.

         SVC   230                SHOULD BE CAPTURED BY SVC SCREENING 
         SVC   231                SHOULD BE CAPTURED BY SVC SCREENING 
         SVC   231                SHOULD BE CAPTURED BY SVC SCREENING 
         SVC   230                SHOULD BE CAPTURED BY SVC SCREENING

Now we can issue some SVC calls and see what happens.

JOB 6840  $HASP373 SVC03    STARTED - INIT 12 - CLASS A - SYS TCS3
JOB 6840  ++++++++ SVC 230 ++++++++                               
JOB 6840  ++++++++ SVC 231 ++++++++                               
JOB 6840  ++++++++ SVC 231 ++++++++                               
JOB 6840  ++++++++ SVC 230 ++++++++                               
JOB 6840   8.55.05   0.00.00   0.00.00  0000   SVC03     MVSSP    
JOB 6840   8.55.05   0.00.00   0.00.00  0000   SVC03     ######## 
JOB 6840  $HASP395 SVC03    ENDED

And when we execute the results are just we would have expected.

Intercepting FIND/BLDL

Now that we know how to intercept SVC calls we can try something more interesting.  When a program is assembled the various macro contained in the source code have to be read from the macro library.  As the assembler reads these macros they are located using SVC 18 (FIND/BLDL).  By intercepting SVC 18 we can list the macros as they are being accessed by the assembler.

First we need to look at the input registers to SVC 18.  Register zero points to a parameter list and register one contains a DCB address or zero.  If the request is for BLDL then the contents register one will be positive.  If the request is for find then contents of register one will be negative.  For this excercise we only care about FIND and not BLDL so we can ignore the parameter list for BLDL.  For a FIND request register zero points to an eight-byte member name.

Now all we have to do is intercept calls to SVC 18 and print out the member name each time we encounter a FIND request.  In order for the assembler to work we will have to reissue the SVC call so the real SVC 18 can locate the member in the PDS.

         MVI   18(R2),X'00'       INTERCEPT SVC 18  BLDL/FIND

First we include SVC 18 in our list of intercepted SVC calls in the screen table.  By setting the corresponding byte in the screen table to X’00’ instead of X’80’ we will cause SVC 18 to be intercepted.

         CLI   0(R9),18           BLDL/FIND
         BE    SVC18

In our SVC processing routine we need to check for SVC number 18 as the interrupt code in the RB.

SVC18    DS    0H                          
         LR    R8,R0              SAVE R0  
         LR    R9,R1              SAVE R1  
         LR    R10,R15            SAVE R15

To process our SVC 18 interrupt we first save the parameter registers passed to the SVC routine.

          LTR   R1,R1                                 
          BP    SKIP18                  BRANCH IF BLDL

Now we check to see if the request is for BLDL or for FIND.  For now we will ignore BLDL requests.

         ST    R0,FWORD           SAVE R0 CONTENTS          
         UNPK  WORK(9),FWORD(5)   UNPACK                    
         TR    WORK(8),HEXTAB-C'0'                          
         MVC   WTO18+18(8),WORK                             
*                                                           
         ST    R1,FWORD                                     
         UNPK  WORK(9),FWORD(5)                             
         TR    WORK(8),HEXTAB-C'0'                          
         MVC   WTO18+30(8),WORK                             
*                                                           
         MVC   WTO18+39(8),0(R8)       COPY FIND MEMBER NAME
*                                                           
*               8.10...15...20...25...30...35...40...45...50
WTO18    WTO   'SVC 18 R0=******** R1=******** ********',   
               ROUTCDE=(1,11)

If it is a FIND request we make the contents of registers zero and one printable.  We do this by first storing the contents of the register into a full word.  Next we unpack the full word and finally we have to translate it to make it printable.  The result is copied into the message area of a WTO along with the member name which is pointed to by register zero (which was copied into register 8 for save keeping).  One think to note here is that we are not writing reentrant code.  This is not the way a SVC routine should be written but for now we can get away with it.

SKIP18   DS    0H                                             
         LR    R0,R8                                          
         LR    R1,R9                                          
         LR    R15,R10                                        
         NI    TCBFLGS7,255-(TCBSVCS)  TURN OFF SVC SCREENING 
         SVC   18                                             
         OI    TCBFLGS7,TCBSVCS        TURN ON SVC SCREENING  
         LR    R14,R11            RESTORE RETURN ADDRESS      
         BR    R14                RETURN TO CALLER

Finally we reissue the SVC call.  First we restore the parameter registers.  In order to allow the SVC call to actually go through instead of being intercepted again, and causing an endless loop, we have to temporarly disable screening by clearing the TCBSVCS bit.  Once we issue the SVC we can once again set the bit to resume screening.  All that remins is to do is to restore the return address and return to the caller.

        MODESET MODE=PROB        GIVE UP SUPERVISOR STATE

In our previous test of SVC screening we reset the APF Authorization bit in the JSCB using my User SVC 245 after getting into supervisor state using MODESET.  Before transfering control to the assembler we need to issue MODESET to restore us to problem state.

         LR    R1,R9              RESTORE PARM REG             
         LINK  EP=IFOX00          TRANSFER CONTROL TO ASSEMBLER

Before calling the assember we need to restore the parameter register contents which was saved off in register nine.

JOB 6911  $HASP373 RUNSVX   STARTED - INIT 12 - CLASS A - SYS TCS3
JOB 6911   6.02.51   0.00.00   0.00.00  0000   RUNSVX    COMPRESS 
JOB 6911  SVC 18 R0=00096C68 R1=FFF69718 IHARB                    
JOB 6911  SVC 18 R0=00096C68 R1=FFF69718 IKJRB                    
JOB 6911  SVC 18 R0=00096C68 R1=FFF69718 IEZXRB                   
JOB 6911  SVC 18 R0=00096C68 R1=FFF69718 IEZBITS                  
JOB 6911  SVC 18 R0=00096C68 R1=FFF69718 IKJTCB                   
JOB 6911  SVC 18 R0=00096C68 R1=FFF69718 TESTAUTH                 
JOB 6911  SVC 18 R0=00096C68 R1=FFF69718 IHBERMAC                 
JOB 6911  SVC 18 R0=00096C68 R1=FFF69718 WTO                      
JOB 6911  SVC 18 R0=00096C68 R1=FFF69718 IHBINNRA                 
JOB 6911  SVC 18 R0=00096C68 R1=FFF69718 DETACH                   
JOB 6911  SVC 18 R0=00096C68 R1=FFF69718 WAIT                     
JOB 6911  SVC 18 R0=00096C68 R1=FFF69718 ATTACH                   
JOB 6911  SVC 18 R0=00096C68 R1=FFF69718 IHBOPLST                 
JOB 6911  SVC 18 R0=00096C68 R1=FFF69718 GETMAIN                  
JOB 6911  SVC 18 R0=00096C68 R1=FFF69718 MODESET                  
JOB 6911  SVC 18 R0=00096C68 R1=FFF69718 SAVE                     
JOB 6911   6.02.51   0.00.00   0.00.00  0000   RUNSVX    ASM     
JOB 6911   6.02.51   0.00.00   0.00.00  0000   RUNSVX    ########
JOB 6911  $HASP395 RUNSVX   ENDED

After assembling and link editing I modified my assembler JCL and replaced the assembler program name (EXEC PGM=IFOX00) with my SVC screening program (EXEC PGM=SVCX) and added a STEPLIB.  Here are the results of running it.  We get a list of all the macros, including the inner macros, that were used in the assembly.

SVC Screening Propagation

We now have SVC screening working but only for one task (TCB).  If we attach a subtask the SVC screening fields are not propagated to the new task.  In later versions of MVS there is an option to set an additional flag in the TCB that will cause ATTACH processing to copy the SVC screening related fields.  We could modify the ATTACH SVC routine to propagate these fields, in fact it would be pretty simple.  Instead we will take a more interesting, and complex way to solve this problem.  We will use SVC screening to intercept ATTACH SVC calls and propagate the SVC screening fields in our intercept routine.

         MVI   42(R2),X'00'       INTERCEPT SVC 42  ATTACH

First we set the corresponding byte in our screen table for SVC 42 (ATTACH).

         CLI   0(R9),42           ATTACH 
         BE    SVC42

In our intercept routine we check for SVC 42 and branch to process it.

SVC42    DS    0H                                       
         LR    R14,R11            RESTORE RETURN ADDRESS
         L     R6,=V(SVX42)       SVC 42 ROUTINE        
         BR    R6                 TRANSFER CONTROL

First we restore the return address to register 14 and then we load the address of our SVC 42 processing routine into register 6 and branch to it. Entry to our routine will be exactly like a SVC call entry.

SVX42    CSECT ,                                         
         USING SVX42,R6           ESTABLISH BASE REGISTER
         USING TCB,R4             MAP TCB                
         USING RBSECT,R5          MAP RB

We start by establishing a base register and mapping the TCB and RB control blocks.

         LR    R8,R14             SAVE RETURN ADDRESS  
         LR    R9,R1              SAVE PARM LIST       
         LR    R10,R15            SAVE ATTACH PARM LIST

Next we save the return address contained in register 14, the parameter list for the attached program contained in register 1, and the parameter list for the ATTACH SVC contained in register 15.

         MODESET EXTKEY=RBT234,WORKREG=2  GET CALLERS PROT KEY

Now we need to get into the storage protect key of the issuer or the SVC. For this we use the MODESET macro and specify EXTKEY=RBT234 indicating the SVC is a type 2, 3, or 4. We also specify register 2 is to be used as a work register.

         GETMAIN R,LV=ATLSTSIZ+4,SP=229              
*                                                    
         LR    R7,R1              POINT TO WORK AREA 
         USING ATTCHLST,R7

Now we getmain some storage to make a copy of the ATTACH parameter list. This is necessary because we will copy the parameter list and modify it before reissuing the SVC. We add four additional bytes to be used by our intercept routine. The allocated storage will be in the same key as the issuer of the SVC. The copy of the parameter area is pointed to by register 7.

         MVI   ATTCHLST+ATLSTSIZ,X'00'   RESET AUTH SWITCH     
*                                                              
         TESTAUTH FCTN=1,STATE=YES,KEY=YES,RBLEVEL=2           
*                                                              
         LTR   R15,R15             IS CALLER AUTHORIZED        
         BNZ   AUTH010             NO - BRANCH                 
*                                                              
         OI    ATTCHLST+ATLSTSIZ,X'80'   SHOW CALLER AUTHORIZED
AUTH010  DS    0H

We will need to know if the issuer of the SVC is APF authorized or not. First we set our flag byte, past the end of the parameter list, to zero indicating the caller is not authorized. Next we use the TESTAUTH macro to determine if the caller was APF authorized. We have the TESTAUTH routine check the JSCB APF authorization bit as well as checking for supervisor state and PSW protect key less than eight. If any of these conditions are true the caller is considered authorized and we set our flag bit.

         MVC   0(ATLSTSIZ,R7),0(R10)    COPY CALLERS PARM LIST

Now we make a copy of the ATTACH parameter list.

        
         TM    ATTCHLST+ATLSTSIZ,X'80'  IS CALLER AUTHORIZED           
         BO    AUTH020                  YES - BRANCH                   
***********************************************************************
*                  RESET ALL AUTHORIZED PARAMETERS                     
***********************************************************************
         NI    ATINDS,255-(ATJSTCB+ATMODE+ATSVAREA+ATKEY+ATDISP+ATJSCB)
         NI    ATFLAGS1,255-ATRSAPF                                    
         XC    ATJSCBA,ATJSCBA                                         
         XC    ATTNSHLV,ATTNSHLV                                       
         XC    ATTID,ATTID                                             
         B     AUTH030             ATDISP ONLY VALID IF APF AUTH       
*                                                                      
*                                                                      
AUTHO20  DS    0H                                                      
         TM    ATINDS,ATDISP       WAS NO DISP SPECIFIED               
         BNO   AUTH030             NO - BRANCH                         
*                                                                      
         OI    ATTCHLST+ATLSTSIZ,X'40'   REMEMBER NO DISP              
AUTH030  DS    0H

If the caller is not APF authorized we clear all of the flags that are only valid for authorized callers and are ignored otherwise. If the caller is authorized we check to see if the ATDISP flag was set indicating the TCB should not be automatically made dispatchable. This is done because we will force this bit before reissuing ATTACH.

         OI    ATINDS,ATDISP      FORCE NO DISPATCH

Now we set the ATDISP flag in our copy of the ATTACH parameter list. Setting this flag bit will make the TCB initially marked non-dispatchable. This is necessary to allow us to set the SVC screening fields in the new TCB before be begins execution.

         SPKA 0                   GET INTO KEY ZERO            
         NI   TCBFLGS7,255-TCBSVCS  TURN OFF SVC SCREENING     
         MODESET EXTKEY=RBT234,WORKREG=2   BACK TO CALLERS KEY 
*                                                              
         LR   R15,R7              OUR UPDATED ATTACH PARM LIST 
         LR   R1,R9               CALLERS R1                   
         SVC  42                  ATTACH                       
         LR   R11,R1              SAVE NEW TCB ADDRESS         
         LR   R12,R15             SAVE RC

Now we get ready to reissue the ATTACH SVC. First we get back into protect key zero. Next we turn off SVC screening for the current TCB so we will not reintercept the call. We then get back into the caller’s protect key using MODESET. We restore the parameter registers 1 and 15 before call SVC 42. We then save the return parameter register values so they can be returned to our caller later.

         SPKA  0                  BACK TO KEY ZERO                 
         OI    TCBFLGS7,TCBSVCS   TURN SVC SCREENING BACK ON       
         LR    R1,R11             RESTORE PARM                     
         LTR   R15,R12            CHECK RC                         
         BNZ   FREEEXIT           EXIT IF NOT ZERO                 
*                                                                  
         L     R1,TCBSVCA2        GET SCREEN TABLE ADDRESS         
         DROP  R4                                                  
         USING TCB,R11            MAP NEW TCB                      
*                                                                  
         ST    R1,TCBSVCA2        STORE SCREEN TABLE ADDR INTO TCB 
         OI    TCBFLGS7,TCBSVCS   TURN ON SVC SCREENING

Now we go back to key zero and restore SVC screening for the current TCB. We then check the return code to see if the ATTACH was successful. If it failed we can to clean up and exit. If it was successful we copy the screen table address from the current TCB into the newly created TCB and set the TCBSVCS flag to active screening.

          L    R15,0(,R11)        POINT TO RB FOR NEW TASK 
          LM   R0,R3,RBGRSAVE     COPY REGISTERS TO NEW RB 
          STM  R0,R3,RBGRSAVE-RBSECT(R15)                  
          LM   R0,R3,RBGRSAVE+16                           
          STM  R0,R3,RBGRSAVE-RBSECT+16(R15)               
          LM   R0,R3,RBGRSAVE+32                           
          STM  R0,R3,RBGRSAVE-RBSECT+32(R15)

Now we copy the register contents from request block into the RB for the newly created task. This will make the initial register contents of the new task appear the same as if we had not intercepted the ATTACH SVC. It really should not make any difference since contents of the registers other than 1, 13, 14, and 15 are not guarenteed to contain any specific values. Still, by copying the contents of registers 0 through 12 we stay complete compatable with the normal operation of ATTACH.

         TM    ATTCHLST+ATLSTSIZ,X'80'   IS CALER AUTH            
         BO    AUTH040                   YES - NO RESET NEEDED    
*                                                                 
         L     R1,TCBGRS12        GET SVRB ROUTINE R12            
         NI    8(R1),255-X'80'    INDICATE ATTACHING TASK NOT AUTH

We have some attitional cleaup to do. Since we always reissue the ATTACH SVC and since we are always in supervisor mode when we reissue the SVC, ATTACH processing always sets up the new TCB as though it was created by an authorized program. This will cause problems when the new TCB is dispatched. If the caller is not authorized we need to reset a flag bit that is passed to the second half to ATTACH processing. When the new TCB is dispatched the initial execution point is in the ATTACH SVC where a new save area is allocated before passing control to a special entry point in the program loader. The program loader checks this flag bit to know if the caller of ATTACH was authorized or not. Since we reissued the ATTACH SVC this bit is always set. Here we reset it to reflect the state of the caller of the original SVC.

         SLR   R1,R1              ZERO R1                  
         ICM   R1,B'0111',ATSTAIXT  ANY STAI/ESTAI         
         BZ    AUTH040              NO - SKIP              
*                                                          
         L     R1,TCBSTAB         POINT TO SCB CHAIN       
AUTH035  DS    0H                                          
         ICM   R1,B'0111',1(R1)   POINT TO NEXT ENTRY      
         BZ    AUTH040            EXIT IF SCB NOT FOUND    
*                                                          
         USING SCB,R1                                      
*                                                          
         CLC   SCBEXIT+1(3),ATSTAIXT  IS THIS OUR SCB ENTRY
         BNE   AUTH035                NO - TRY NEXT        
*                                                          
         NI    SCBFLGS2,255-(SCBSUPER)  TURN OFF SUPER BIT 
AUTH040  DS    0H

We have one last thing to clean up before we can let the new TCB dispatch. If a STAEI/ESTAI was specified on the ATTACH we need to reset the supervisor mode bit in the STAE Control Block (SCB) if our caller was not authorized. Failre to properly set this bit could allow an unauthorized program to receive control in authorized mode when the ESTAE exit is called. If a STAEI/ESTAEI exit was specified on the ATTACH we loop through the SCB chain to locate the associated SCB and clear the SCBSUPER bit.

         TM    ATTCHLST+ATLSTSIZ,X'40'  SHOULD WE LEAVE NON-DISP 
         BO    AUTH050                  YES - BRANCH             
*                                                                
         STATUS RESET,ND,(R11),(12)                              
AUTH050  DS    0H

Now unless the caller was authorized AND specified the new task should not dispatch we now issue the STATUS macro to reset the task dispatchability status. This will allow the newly created task to begin execution.

FREEEXIT DS    0H                                             
         DROP  R11                                            
         USING TCB,R4                                         
         MODESET EXTKEY=RBT234,WORKREG=2  GET INTO CALLERS KEY
*                                                             
         FREEMAIN R,LV=ATLSTSIZ,A=(R7),SP=229                 
*                                                             
         SPKA  0                  BACK TO KEY ZERO

Now all that is left is to clean up before exiting. First we use MODESET to get back into the caller’s key so we can FREEMAIN the work area we previously allocated with GETMAIN. We then go back to key zero.

         LR    R1,R11             SET TCB ADDRESS        
         LR    R15,R12            SET ATTACH RC          
SVCEXIT  DS    0H                                        
         SPKA  0                  GET INTO KEY ZERO      
         LR    R14,8              RESTORE RETURN ADDRESS 
         BR    R14

Before exiting we need to restore the return values for register 1 and 15 that were previously saved.

         IKJTCB ,   
         IKJRB ,    
         IEZATTCH , 
         IEZJSCB ,  
         IHASCB ,

The control block mapping macros and register equates (not shown here) complete the SVC 42 intercept code.

         ATTACH EP=IFOX00,ECB=ECB                                     
         ST    R1,PTRTCB          SAVE TCB ADDRESS 
         WAIT  1,ECB=ECB                           
         DETACH PTRTCB            DETACH TCB

Now if we replace the LINK=IFOX00 to an ATTACH we can test the SVC 42 intercept logic.

JOB 6912  $HASP373 RUNSVX   STARTED - INIT 12 - CLASS A - SYS TCS3
JOB 6912  20.04.34   0.00.00   0.00.00  0000   RUNSVX    COMPRESS 
JOB 6912  SVC 18 R0=00096C68 R1=FFF69718 IHARB                    
JOB 6912  SVC 18 R0=00096C68 R1=FFF69718 IKJRB                    
JOB 6912  SVC 18 R0=00096C68 R1=FFF69718 IEZXRB                   
JOB 6912  SVC 18 R0=00096C68 R1=FFF69718 IEZBITS                  
JOB 6912  SVC 18 R0=00096C68 R1=FFF69718 IKJTCB                   
JOB 6912  SVC 18 R0=00096C68 R1=FFF69718 TESTAUTH                 
JOB 6912  SVC 18 R0=00096C68 R1=FFF69718 IHBERMAC                 
JOB 6912  SVC 18 R0=00096C68 R1=FFF69718 WTO                      
JOB 6912  SVC 18 R0=00096C68 R1=FFF69718 IHBINNRA                 
JOB 6912  SVC 18 R0=00096C68 R1=FFF69718 DETACH                   
JOB 6912  SVC 18 R0=00096C68 R1=FFF69718 WAIT                     
JOB 6912  SVC 18 R0=00096C68 R1=FFF69718 ATTACH                   
JOB 6912  SVC 18 R0=00096C68 R1=FFF69718 IHBOPLST                 
JOB 6912  SVC 18 R0=00096C68 R1=FFF69718 GETMAIN                  
JOB 6912  SVC 18 R0=00096C68 R1=FFF69718 MODESET                  
JOB 6912  SVC 18 R0=00096C68 R1=FFF69718 SAVE                     
JOB 6912  20.04.34   0.00.00   0.00.00  0000   RUNSVX    ASM     
JOB 6912  20.04.34   0.00.00   0.00.00  0000   RUNSVX    ########
JOB 6912  $HASP395 RUNSVX   ENDED

Upon execution we see that SVC 42 was intercepted and SVC screening was propagated since we are still intercepting the FIND SVC calls.