NT4/private/ntos/nthals/halalpha/ev4ints.s

273 lines
7.9 KiB
ArmAsm
Raw Normal View History

2001-01-01 00:00:00 +01:00
//++
//
// 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