summaryrefslogblamecommitdiffstats
path: root/private/ntos/nthals/halalpha/ev4ints.s
blob: aaa06db8751d90fad1429d0f4cfbc5fcd8639927 (plain) (tree)















































































































































































































































































                                                                              
//++
//
// Copyright (c) 1994  Microsoft Corporation
//
// Module Name:
//
//    ev4ints.s
//
// Abstract:
//
//    This module implements EV4-specific interrupt handlers.
//    (the performance counters)
//
// Author:
//
//    John Vert (jvert) 15-Nov-1994
//
// Environment:
//
//    Kernel mode only.
//
// Revision History:
//
//--
#include "halalpha.h"

#define PC0_SECONDARY_VECTOR 11
#define PC1_SECONDARY_VECTOR 13
#define PcProfileCount0 PcHalReserved+8
#define PcProfileCount1 PcProfileCount0+4
#define PcProfileCountReload0 PcProfileCount1+4
#define PcProfileCountReload1 PcProfileCountReload0+4

        .struct 0
        .space  8                       // reserved for alignment
PrRa:   .space  8                       // space for return address
PrFrameLength:                          //

        SBTTL("Performance Counter 0 Interrupt")
//++
//
// VOID
// HalpPerformanceCounter0Interrupt
//    )
//
// Routine Description:
//
//   This function is executed as the result of an interrupt from the
//   internal microprocessor performance counter 0.  The interrupt
//   may be used to signal the completion of a profile event.
//   If profiling is current active, the function determines if the
//   profile interval has expired and if so dispatches to the standard
//   system routine to update the system profile time.  If profiling
//   is not active then the function performs a secondary dispatch for
//   performance counter 0.
//
// Arguments:
//
//    TrapFrame (fp/s6) - Supplies a pointer to the trap frame for
//                            the interrupt.
//
// Return Value:
//
//    TRUE is returned.
//
//--

        NESTED_ENTRY(HalpPerformanceCounter0Interrupt, PrFrameLength, zero )

        lda     sp, -PrFrameLength(sp)  // allocate a stack frame
        stq     ra, PrRa(sp)            // save the return address

        PROLOGUE_END                    //

        call_pal rdpcr                  // v0 = pcr base address

        ldl     t0, PcProfileCount0(v0) // capture the current profile count
        beq     t0, 20f                 // if eq, profiling not active

//
// Profiling is active.  Decrement the interval count and if it has
// reached zero then call the kernel profile routine.
//

        subl    t0, 1, t0               // decrement the interval count
        bne     t0, 10f                 // if ne, interval has not expired

//
// The profile interval has expired.  Reset the profile interval count
// and process the profile interrupt.
//

        ldl     t0, PcProfileCountReload0(v0)   // get the new tick count
        stl     t0, PcProfileCount0(v0) // reset the profile interval count

        ldl     a1, HalpProfileSource0
        bis     fp, zero, a0            // pass trap frame pointer
        ldl     t1, __imp_KeProfileInterruptWithSource
        jsr     ra, (t1)                // process the profile interrupt

        br      zero, 40f               // common return

//
// The profile interval has not expired.  Update the decremented count.
//

10:
        stl     t0, PcProfileCount0(v0) // update profile interval count
        br      zero, 40f               // common return

//
// Profiling is not active.  Therefore, this interrupt was caused by
// a performance counter driver.  Deliver a secondary dispatch.
//

20:

        ldil    a0, PC0_SECONDARY_VECTOR // get IDT vector for secondary
        s4addl  a0, v0, a0              // a0 = PCR + IDT index
        ldl     a0, PcInterruptRoutine(a0) // get service routine address
        jsr     ra, (a0)                // call interrupt service routine

//
// Setup for return.
//

40:
        ldil    v0, TRUE                // set return value = TRUE
        ldq     ra, PrRa(sp)            // restore return address
        lda     sp, PrFrameLength(sp)   // deallocate the stack frame
        ret     zero, (ra)              // return

        .end    HalpPerformanceCounter0Interrupt


        SBTTL("Performance Counter 1 Interrupt")
//++
//
// VOID
// HalpPerformanceCounter1Interrupt
//    )
//
// Routine Description:
//
//   This function is executed as the result of an interrupt from the
//   internal microprocessor performance counter 1.  The interrupt
//   may be used to signal the completion of a profile event.
//   If profiling is current active, the function determines if the
//   profile interval has expired and if so dispatches to the standard
//   system routine to update the system profile time.  If profiling
//   is not active then the function performs a secondary dispatch for
//   performance counter 1.
//
// Arguments:
//
//    TrapFrame (fp/s6) - Supplies a pointer to the trap frame for
//                            the interrupt.
//
// Return Value:
//
//    TRUE is returned.
//
//--

        NESTED_ENTRY(HalpPerformanceCounter1Interrupt, PrFrameLength, zero )

        lda     sp, -PrFrameLength(sp)  // allocate a stack frame
        stq     ra, PrRa(sp)            // save the return address

        PROLOGUE_END                    //

        call_pal rdpcr                  // v0 = pcr base address

        ldl     t0, PcProfileCount1(v0) // capture the current profile count
        beq     t0, 20f                 // if eq, profiling not active

//
// Profiling is active.  Decrement the interval count and if it has
// reached zero then call the kernel profile routine.
//

        subl    t0, 1, t0               // decrement the interval count
        bne     t0, 10f                 // if ne, interval has not expired

//
// The profile interval has expired.  Reset the profile interval count
// and process the profile interrupt.
//

        ldl     t0, PcProfileCountReload1(v0)  // get the new tick count
        stl     t0, PcProfileCount1(v0) // reset the profile interval count

        ldl     a1, HalpProfileSource1
        bis     fp, zero, a0            // pass trap frame pointer
        ldl     t1, __imp_KeProfileInterruptWithSource
        jsr     ra, (t1)                // process the profile interrupt

        br      zero, 40f               // common return

//
// The profile interval has not expired.  Update the decremented count.
//

10:
        stl     t0, PcProfileCount1(v0) // update profile interval count
        br      zero, 40f               // common return

//
// Profiling is not active.  Therefore, this interrupt was caused by
// a performance counter driver.  Deliver a secondary dispatch.
//

20:

        ldil    a0, PC1_SECONDARY_VECTOR // get IDT vector for secondary
        s4addl  a0, v0, a0              // a0 = PCR + IDT index
        ldl     a0, PcInterruptRoutine(a0) // get service routine address
        jsr     ra, (a0)                // call interrupt service routine

//
// Setup for return.
//

40:
        ldil    v0, TRUE                // set return value = TRUE
        ldq     ra, PrRa(sp)            // restore return address
        lda     sp, PrFrameLength(sp)   // deallocate the stack frame
        ret     zero, (ra)              // return

        .end    HalpPerformanceCounter1Interrupt

//++
//
// VOID
// HalpWritePerformanceCounter(
//     IN ULONG PerformanceCounter,
//     IN BOOLEAN Enable,
//     IN ULONG MuxControl OPTIONAL,
//     IN ULONG EventCount OPTIONAL
//     )
//
// Routine Description:
//
//     Write the specified microprocessor internal performance counter.
//
// Arguments:
//
//     PerformanceCounter(a0) - Supplies the number of the performance counter
//                              to write.
//
//     Enable(a1) - Supplies a boolean that indicates if the performance
//                  counter should be enabled or disabled.
//
//     MuxControl(a2) - Supplies the mux control value which selects which
//                      type of event to count when the counter is enabled.
//
//     EventCount(a3) - Supplies the event interval when the counter is
//                      enabled.
//
// Return Value:
//
//     None.
//
//--

	LEAF_ENTRY(HalpWritePerformanceCounter)

	call_pal wrperfmon		// write the counter

	ret	zero, (ra)		// return

	.end HalpWritePerformanceCounter