CSCI 468    Spring, 2007      SOS -- B       R. P. Rannie
                    
 Changes -- Addition of PIE (Program Interrupt Element)

 You will set aside a 32 byte area at the highest address in the user
 region.  This will be the PIE.  This area should be initialized to
 8CL4'PIE'.  Note:  Just move four bytes and then "ripple" via MVC.

 Changes -- Addition of JCL Parm Processing

 You will establish a 'JCL Input Parms' area (length to be determined)
 just below the PIE in each user 4K region.  The parm will be found 
 within the 80-byte 'Parm Card' that is read in by the MS.  You will
 parse this 80 byte input record searching for the string of six
 characters ',PARM='.  These six characters will be followed by a parm
 in one of three formats.  (1) Only a single blank, indicating that
 there is NO parm (i.e., a parm of zero length!) (2) A series of
 non-blank characters that will be terminated by a blank in which case
 the series of characters constitute the parm.  (3) A beginning and
 ending single quote surrounding a string of characters (which may
 include blanks) in which case the string enclosed in quotes is the parm.

 The size and configuration of this area will correspond to that of
 a real 'JCL Input Parms' area, ending (and starting) on a fullword
 boundary; thus:       
                           Note: Pad? and Fill?;, are they needed??

 X'80',AL3(length field),XL2'Pad?',AL2(parm length),PARM,XL1'Fill?'

 On entry to the user's program, R1 points to the full word (on a
 full word boundary) that is the start of the 'JCL Input Parms'.
 Note that all of this 'JCL Input Parm' area will end on a full word
 boundary that is the start of the PIE of the users 4K area.  Use
 X'00's for padding in the Parm fields (at the '?' locations) ONLY
 where REQUIRED, (i.e., 2 bytes) before the 2-byte length field (if
 needed) and 1 byte at the END of the actual JCL parm itself IF its
 length is ODD)!  Before dispatching the user program, store the
 value that you stored into R1 into the users TCBAPARM field.

 Changes -- 18 Fullword save area

 Your 18 fullword save area for this 4K region will be located at an
 address just below the parm area.  Standard rules for the save area
 (including zeroing the second four bytes of the save area).  Before
 dispatching the users program, store the value that you stored into
 R13 into the users TCBFSA field.

 Changes to SVC 8

 You will now use LOADER rather than LOADERX as the SVC 8 module.
 LOADER is a Type-2-SVC version of SVC 8.  You will need to set the
 flags for SVC 8 in the SVCTABLE accordingly.

 Changes -- Dispatcher:  Report BOTH types of time at job end.

 Your Job Termination Message from the Dispatcher JOB END code will
 now report BOTH Problem state task time and Supervisor state task
 time.  

 Changes -- ALL FLIH:  Timing

 You have seen the 'time' fields in the ASSIST-V traces.  These
 values have been obtained from the simulated time.  This timer is
 the same one to which you have access at X'50'.  You will
 henceforth keep track of the amount of CPU time used by each of the
 tasks.  In each TCB are TCBTDISP (dispatch time) and TCBTCPUP (sum
 of CPU time used - TASK, Problem State), and TCBTCPUS (sum of CPU
 time used - TASK, Supervisor State).

 Before the first dispatch of any TCB all of these fields must have
 been set to zero.  At each dispatch, just before LM 0,15,TCBGRS ,
 you place the current value of the timer in TCBTDISP.  At each
 interrupt, FIRST THING, move the current value of the timer to a
 low core location, LOWTIME.  Then, after register and PSW saving in
 the FLIH, SUBTRACT LOWTIME from TCBTDISP to get the elapsed CPU
 time and ADD this amount to TCBTCPUP (or TCBTCPUS, depending on the
 state of the interrupted PSW) and store the accumulated CPU TASK
 time into the appropriate TCB TASK time accumulation field.

 Invoking SVC routines

 There are basically two types of SVC routines.  A Type 1 SVC
 routine always runs in supervisor state, with all interrupts
 disabled (really with I/O interrupts disabled, because you need to
 run with Machine Check, External, and Program Checks ENABLED).  The
 Type 1 routine should not contain code to cause any interrupts
 (program interrupts or SVC interrupts) during its execution.  Type
 1 SVCs CANNOT issue OTHER SVC calls!  The Type 1 routines are meant
 to be handled quickly, so that interrupts are disabled for as short
 a time as possible.  An important example is SVC 0, which handles
 I/O operations.  An SVC routine which is not Type 1 runs with I/O
 interrupts enabled, and it is permitted to issue (some) further SVC
 instructions.

 On entry to any SVC routine(module) from the SVC FLIH, the
 following are assumed as the contents of the specified registers.
 Remember, this is just a convention; other conventions could be
 used; we are following the MVS conventions.

   Regs 0,1,13,15 :  In Parms.  Contents at the time of SVC instruction.
   Reg  3 :          CVT Address.
   Reg  4 :          TCB Address.
   Reg  5 :          RB  Address.
   Reg  6 :          The entry point of this SVC routine.
   Reg 14 :          Return address.  The SVC routine branches here
                     when it is finished.

 Your FLIH should Not have changed the four input parameter
 registers and you should have loaded the correct values into
 registers 3, 4, and 5.  Register 6, the A(SVC routine) should have
 been loaded from the SVCTABLE, and if R6.NE.0, proceed as follows:

 Determine SVC as Type 1 or Type 'Other'

 Note that there are ONLY TWO(2) bits set in each SVC table entry to
 indicate whether the SVC is Type 1, 2, or 3/4.  THE TEST YOU USE TO
 DETERMINE SVC TYPE MAY ONLY TEST THESE TWO(2) BITS!  For type other
 (Non-Type-1) SVCs you will now need to 'Schedule an SVRB.'

     if SVC is Type 1 do;
         Test/Set TYP1FLAG from C'0' to C'1'         Wrong? XOPC 25
         BALR 14,6 To SVC routine (Return from routine via R14)
         Test/Set TYP1FLAG from C'1' to C'0'         Wrong? XOPC 25
         Store Regs 0,1,15 in TCBGRS area; these are values
             that are returned BY the SVC routine.
         B  Dispatcher
     else do;
         Schedule a new SVRB (see description below)  Note that
             this includes copying saved registers from the TCB to
             the SVRB.  (Copy both TCBGRS and TCBFRS.)
         Get the A(CVTEXIT) into R14.
         Store Regs 3,4,5,6,14 in the appropriate TCBGRS save areas.
         Create a PSW in the SVRB, with instruction address taken
             from R6, supervisor state, Key 0, interrupts enabled.
         B  Dispatcher
     endif;

 The effect of this logic is that for Type 1 SVCs, the SVCFLIH will BALR
 into the Type 1 SVC routine.  (Later the Type 1 routine returns, via 
 R14, to the SVCFLIH, which branches to the Dispatcher.)  However, for 
 other types of SVCs, the SVCFLIH does not branch to/from the SVC 
 routine.  Instead it sets up control blocks so that the next time the
 task (TCB) is dispatched, the SVC routine will be entered.  This is a
 method of allowing an SVC to be executed from within an SVC routine,
 but still preventing an SVC from being executed from within the
 interrupt handler.

 Scheduling an SVRB:

     Get an SVRB from the CB Pool and clear it (XC!).
     Format as an SVRB:  RBTYPE = C'SVRB', RBFLGS3 = X'00'.
     Put A(TCB) into RBTCB.
     Store R5 (which should be A-current PRB, and with the high
      byte cleared to zero), into RBLINK of the SVRB.
     Update R5, that is, Load R5 with the address of this SVRB.
     (The USING RB,R5 should still be in effect.)
     ST    R5,TCBRB  Store SVRB pointer in TCB.

 NOTE:  Arrange your 'Type-1' code and your 'Type-Other' code so
 that the 'Type-1' code comes BEFORE your 'Type-Other' code.  Each
 section of code should contain independent instructions for
 branching to the dispatcher.  (Reasons for this will become
 apparent later!)

 Paper Saving in IPL and elsewhere!

 The XREF, while a useful debugging tool, will become quite large,  
 It can be suppressed by putting ",XREF=0" following "L=60" in the
 Assist-V parms line.  A run without this XREF setting will provide
 all of the cross references if they are needed for debugging.

 The XOPC instructions (4 = turn trace off, 2 = turn trace back on)
 can be used to reduce the volume of trace output from Assist-V.
 However, in cases where debugging efforts are impeded by the lack
 of trace information, reason dictates that the trace should be
 turned back on!

 In the 'infinite loop' used in IPL to find the 'top' of available
 memory, use XOPC 4 so that only ONE trace entry for an SSK
 instruction is output.  An XOPC 2 should be located immediately
 after the MVC instruction at label AFTERLOP.

 The SVC 8 instruction in your Master Scheduler should be embedded in
 instructions that will bracket the SVC 8 with an XOPC 2 / XOPC 4 
 such that only the first call to SVC 8 will provide SVC 0 traces.

 Program  Location  Key/  Pad   Contents of     Function
                    Fetch Char. FPR: 0,2,4,6

 OBJMOD7Y XL4'9000' X'98' C'B'  Default       End via user SVC 3
 OBJMOD7  XL4'A000' X'A8' C'C'  Default       End via user BR R14

 JCL

 Your JCL for the FT05F001 should now be of the following form:
 //FT05F001 DD DSN=T90RPR1.CS468PUB.OBJLIB(PARM1111),DISP=SHR
 //         DD DSN=T90RPR1.CS468PUB.OBJLIB(OBJMOD7Y),DISP=SHR
 //         DD DSN=SYS1.MACLIB(FM),DISP=SHR
 //         DD DSN=T90RPR1.CS468PUB.OBJLIB(ALLNINES),DISP=SHR
 //         DD DSN=T90RPR1.CS468PUB.OBJLIB(PARM2222),DISP=SHR
 //         DD DSN=T90RPR1.CS468PUB.OBJLIB(OBJMOD7),DISP=SHR
 //         DD DSN=SYS1.MACLIB(DSG),DISP=SHR
 //         DD DSN=T90RPR1.CS468PUB.OBJLIB(ALLNINES),DISP=SHR