From:	MERC::"uunet!WKUVX1.BITNET!MacroMan" 30-MAY-1992 14:20:00.64
To:	MACRO32@WKUVX1.BITNET
CC:	
Subj:	Previous posting of code

Date sent:  30-MAY-1992 11:06:16


        Yesterday I posted some code that I could not get to
        work.  I ended up fixing all the problems but one -
        that is, it would never bugcheck.  Even if I put a
        jsb g^ini$brk _after_ the bugcheck, it would get
        to the breakpoint.

        Thanks to Gerard Newman of TGV for helping me to
        see that the BUG_CHECK macro requires that the
        FATAL keyword be in upper case!!!

        Code below for your edification...

        Ehud

--
Ehud Gavron     (EG76)
gavron@Spades.ACES.COM

        .TITLE  FIXUP_EXE$UBCLKINT      Make clock interrupts monitor time
;                                       spent at high IPL.
        .IDENT  /V1.1.0-28May92/
;++
;
; FIXUP_EXE$UBCLKINT.MAR        28-May-1992     Ehud Gavron
;
; If the CPU spends an inordinate amount of time at high IPL then we drop
; all LAT sessions.  This code will check and see how long it stays at the
; high IPL and bugcheck if too long.
;
; Although no merchantability is expressed or implied, this
; code was developed for and will work under V5.4-2.
;
; This code is based on code written for personal use, and is therefore
; Copyright 1992 ACES Incorporated.  All rights reserved save those
; explicitly listed below.
;
; It is permitted to assemble, link, and use this code provided
; that no financial gain is made by the procurer or executor of
; this code as a result of doing so.
;
;       Ehud Gavron             gavron@Spades.ACES.COM
;
;--
; V1.0.0        Created because I'm not getting enough interesting
;               kernel-coding to do in my regular job.
;
; V1.1.0        modified to do exe$ubclkint
;
; Definitions
;
        .library        "sys$Library:lib.mlb"                   ; find $xxxdefs
        .link           "sys$system:sys.stb"/selective_search   ; find xxx$x_xs

        $opdef          ; Opcode definitions (for op$_jmp...)
        $pcbdef         ; Process Control Block offsets (to get PCB$L_JIB)
        $phddef         ; Process Header offsets (to get PHD$L_CPUTIM)
        $jibdef         ; Job Information Block offsets (to get JIB$T_USERNAME)
        $prtdef         ; Page Protection definitions (for PRT$C_URKW)
        $psldef         ; Processor Status Longword offsets (for PSL$M_IPL)
        $ptedef         ; Page Table Entry definitions (to get PTE$x_PROT)
        $ssdef          ; System Service status values (for normal status)

;
; Offsets I stole from the VAX Architecture manual:
;
SCB_L_CMKRNL    =       ^X40
SCB_L_CMEXEC    =       ^X44

;
; Location of vector symbol and addresses:
;
fv_symbol:      .blkl   1       ; The global symbol to find the code for
fv_vector:      .blkl   1       ; The address of the code
;
; Argument list to pass it to FIND_VECTOR:
;
fv_arglst:      .long   2
                .address fv_symbol
                .address fv_vector
;
; Macros:
;
        .macro  cmd_store       cmd,cmdargs     ; Store a command as a string
'cmd'_inst: 'cmd' 'cmdargs'                     ; Descriptor.  Eventually this
'cmd'_len = . - 'cmd'_inst                      ; will lead to a generic patch-
'cmd'_desc:     .long   'cmd'_len               ; in-memory routine.
                .address 'cmd'_inst
        .endm

        .macro  FIND_AND_DESTROY symb           ; A temporary macro to avoid
        movl    #symb,fv_symbol                 ; Having repetitious-looking
        $cmkrnl_s       routin=find_vector,-    ; source-code.  This one will
                        arglst=fv_arglst        ; find a symbol, and call the
        $cmkrnl_s       routin=fixup_k,-        ; fixup routine.
                        arglst=fv_arglst
        .endm

;
; Start of user-mode code:
;
        .Entry  Fixup,^m<>
        find_and_destroy        exe$ubclkint    ; Patch it!
        Ret                                     ; End!

;
; Start of kernel-mode code:
;
        .entry  FIND_VECTOR,^m<r2,r3,r4,r5,r6,r7,r8,r9,r10,r11>
;
; Find out which system service or jump vector it is today...
;
        movl    @4(ap),r7               ; Address of vector requested
        cmpw    (r7),#op$_jmp!<^x9f00>  ; Check for JMP @#
        beql    10$                     ; It is, go use it
        addl    #2,r7                   ; Move past the entry mask
        cmpw    (r7),#op$_jmp!<^x9f00>  ; Is it a JMP @#
        beql    10$                     ; Yup, go deal with it
        movl    #SCB_l_cmkrnl,r10       ; Prepare for it being a CHMK
        cmpb    (r7),#op$_chmk          ; Is it a CHMK #n
        beql    20$                     ; Yup, go deal with it
        movl    #SCB_l_cmexec,r10       ; Prepare for it being a CHME
        cmpb    (r7),#op$_chme          ; Is it a CHME #n
        beql    20$                     ; Yup, go deal with it
        movl    #ss$_unsupported,-      ; Eeek, don't know what it is...
                r0                      ; So tell user it's unsupported
        ret                             ; and go back to user mode!

;
; So now we extract the address from the JMP instruction:
;
10$:
        addl2   #2,r7                   ; Get nn from JMP @#nn
        movl    (r7),@8(ap)
        movl    r7,@4(ap)
        movl    #ss$_normal,r0
        ret
;
; So now we get the number of the exception...
;
20$:
        addl2   #2,r7                   ; Get address of #nn from CHMx #nn
        movzbl  (r7),r8                 ; Get nn into R8
;
; So now we find the dispatcher address
;
        movl    @#exe$gl_scb,r1         ; Get address of System Control Block
        addl2   r10,r1                  ; Get address of correct dispatcher
        movl    (r1),r1                 ; Get address of exe$cmodxxxx where
                                        ; xxxx is either krnl or exec
;
; We look in its code for the dispatch vector table
;
        movab   movaq_inst,r2           ; Address of our MOVAQ instruction
        movzwl  (r2),r5
        addl3   #^xff,r1,r3             ; Address past MOVAQ fer shure
30$:
        movzwl  (r1),r6
        cmpw    r6,r5                   ; Have we found a MOVAQ?
        beql    40$                     ; Yup!
        aobleq  r3,r1,30$
        movl    #ss$_nodata,r0          ; Whoops, couldn't find it...
        ret                             ; So go back to user mode... sigh

;
; Ok, here R1 points to the start of a MOVAQ instruction that looks like:
;       MOVAQ CMOD$AR_mode_DISPATCH_VECTOR[R1],R1
; which translates to bytes:    51hhllCF417E with hhll being the offset
; from the last byte (51).  We first save this current R1
;
40$:
        movl    r1,r9                   ; Address of MOVAQ
        movl    r1,r7                   ; Saved
;
; Then we find the offset
;
        addl2   #3,r9                   ; Address of hhll (word)
        movzwl  (r9),r3                 ; R3 = offset
;
; Then we add get the address of the end of the instruction
;
        addl2   #5,r7                   ; Address of last byte of instruction
;
; Then we add the offset
;
        addl2   r3,r7                   ; R7 = CMOD$AR_mode_DISPATCH_VECTOR
;
; Then we take our CHMn code and multiply by 8 (quadword vectors) and add
;
        ashl    #3,r8,r6                ; Vector offset
        addl2   r6,r7                   ; Our vector
        addl2   #4,r7                   ; The address [2nd longword of vector]
        movl    (r7),@8(ap)             ; Return this address
        movl    r7,@4(ap)               ; Return address of address
        movl    #ss$_normal,r0
        ret


        .entry FIXUP_K,^m<r2,r3,r4,r5,r6,r7,r8,r9,r10,r11>
;
; ++
; Make EXE$UBCLKINT monitor previous IPL levels for a large amount of time
; at high IPL.
;
;       Stack:
;               @4(ap)  -       address where old address is stored (CHMn)
;               @8(ap)  -       old address of EXE$UBCLKINT
;
; Allocate a buffer in system space (nonpaged pool) to hold
; all the code to do this stuff...
;
        movl    #code_len,r1
        jsb     g^exe$alononpaged
        blbs    r0,10$
        ret
;
; Copy the code into the pool.
;
10$:    movl    r2,r6                   ; Save pointer to new npagedyn
        movc3   #code_len,-             ; Copy code into npagedyn
                w^code,(r6)
;
; First we prepare the JMP instruction to stick in the front of the old
; EXE$UBCLKINT.  We do this because it can be JSB'd to from Kernel
; mode.  If that occurs then just revectoring it doesn't help...
;
; Take the second jump at the end of the code and make it point to here...
;
        addl3   #<jump2-code+2>,r6,r2
        movl    r6,(r2)
;
; Now we change the jump instruction at the end to point to the real
; code plus a couple of instructions.  Then we'll overwrite the
; first few instructions with the jump2 we prepared.  Finally at the
; end of our code segment are the instructions (from the listing) that
; we overwrote...
;
;
;
; NOTE: The location being bashed here is the clock interrupt. It really
;  needs to be modified to by synch'd at IPL_POWER (ipl 31) so no
;  interrupts can come in and see the patch partly done! _ G. Everhart
;  This code doesn't have anything obvious to do that...
;  Caveat emptor...
        movl    @8(ap),r2               ; Address of entry point to exe$...
        addl3   #<jump-code+2>,r6,r7    ; Address of jump data
        addl3   r2,#^x0b,r3             ; R3 --> exe$setprv+b
        movl    r3,(r7)                 ; Make jump go to exe$setprv + 0b
        movl    @4(ap),r7               ; Store pointer to address of exe$...
        movl    r2,r8                   ; Save pointer to exe$...
        movl    #prt$c_uw,r9                    ; Set for ERKW
        lock    lockname=MMG,-          ; Raise IPL, acquire spinlock
                lockipl=#IPL$_MMG,-
                preserve=NO
        jsb     g^mmg$svaptechk         ; Get SVAPTE in R3
        extzv   #pte$v_prot,#pte$s_prot,(r3),r10
        insv    r9,#pte$v_prot,#pte$s_prot,(r3)
        invalidate_tb
        movl    r7,r2
        jsb     g^mmg$svaptechk
        extzv   #pte$v_prot,#pte$s_prot,(r3),r10
        insv    r9,#pte$v_prot,#pte$s_prot,(r3)
        invalidate_tb                   ; Translation Buffer Invalidate All
        movl    r6,(r7)                 ; Update vector
        movc3   #jump_len,-
                <jump2-code>(r6),(r8)   ; Put the second jump in...

        unlock  lockname=MMG,-          ; Release lock
                newipl=#0

        movl    #ss$_normal,r0
        ret

code:
;
; We check for this as follows:
;
;       If (data_ipl == 34) {   /* must initialize it */
;          data_ticks = 0;
;          data_ipl = 0;
;       }
;
;       data_ipl = IPL          /* get previous IPL off of stack */
;       if (data_ipl <=9) {     /* High IPL? */
;          data_ticks = 0;      /* nope */
;          }
;       else {                  /* High IPL?  YUP! */
;          if (data_ipl != ipl) { /* Repeat count? */
;             data_ipl = ipl;     /* nope */
;             }
;          else {               /* Repeat count?  YUP! */
;             data_ticks++;
;             if (data_ticks >= 200) {
;                bugcheck(bug$_vpiplhigh);
;                }
;             }
;          }
;
;
IPL = 0
SR1 = 4
SR0 = 8
CNT = 12
        movl    r0,-(sp)                        ; store r0
        movl    r1,-(sp)                        ; store r1
        movab   data_ipl,r1                     ; base of data area
        movl    (sp)+,SR1(r1)                   ; store r1 in   4(data_area)
        movl    (sp)+,SR0(r1)                   ; store r0 in   8(data_area)
        cmpl    (r1),#34                        ; see if this is first call
        bneq    10$                             ; nope
        clrl    IPL(r1)                         ; clear ipl
        clrl    CNT(r1)                         ; clear count
10$:    movl    4(sp),r0                        ; saved PSL off of stack
        extzv   #psl$v_ipl,#psl$s_ipl,r0,r0     ; get IPL
        cmpl    r0,#8                           ; is it 8 or higher?
        bgtr    20$                             ; yes, go count
        clrl    CNT(r1)                         ; clear count (low ipl)
        brw     30$                             ; and exit
20$:    incl    CNT(R1)                         ; how long have we been here?
        movl    r0,IPL(r1)                      ; store this IPL...
        cmpl    CNT(r1),#150                    ; are we expired
        blss    30$                             ; nope...
        setipl  ipl=#31,environ=uniprocessor    ; let nobody stop us!
        bug_check PGFIPLHI,FATAL                ; bug check
30$:
;
; Restore registers:
;
        movl    sr0(r1),r0                      ; restore r0
        movl    sr1(r1),r1                      ; restore r1
;;; The following data NOT from [v54.sys.lis]timeschdl.lis but from anal/sys
;;;
        movq    r0,-(sp)
        bicl3   @#smp$gl_base_msk,sp,r1
;;;
;;; End of DEC code...
;
; start of data area:
;
jump:
        jmp     @#00000000
jump_len = . - jump
jump2:
        jmp     @#00000000
data_ipl:       .long   34
saved_r1:       .blkl   1
saved_r0:       .blkl   1
count:          .blkl   1
patch_space:    .blkl   200
code_len = . - code
        cmd_store       movaq   <w^10[r1],r1>
        .end    fixup

