mirror of https://github.com/lianthony/NT4.0
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
300 lines
8.5 KiB
300 lines
8.5 KiB
//++
|
|
//
|
|
// Copyright (C) 1994,1995 Microsoft Corporation
|
|
//
|
|
// Module Name:
|
|
//
|
|
// ev4ints.s
|
|
//
|
|
// Abstract:
|
|
//
|
|
// This module implements EV4-specific interrupt handlers.
|
|
// (the performance counters)
|
|
//
|
|
//
|
|
// Environment:
|
|
//
|
|
// Kernel mode only.
|
|
//
|
|
//
|
|
//--
|
|
#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
|
|
// Halp21064PerformanceCounter0Interrupt
|
|
// )
|
|
//
|
|
// 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(Halp21064PerformanceCounter0Interrupt, 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, Halp21064ProfileSource0
|
|
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 Halp21064PerformanceCounter0Interrupt
|
|
|
|
|
|
SBTTL("Performance Counter 1 Interrupt")
|
|
//++
|
|
//
|
|
// VOID
|
|
// Halp21064PerformanceCounter1Interrupt
|
|
// )
|
|
//
|
|
// 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(Halp21064PerformanceCounter1Interrupt, 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, Halp21064ProfileSource1
|
|
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 Halp21064PerformanceCounter1Interrupt
|
|
|
|
//++
|
|
//
|
|
// VOID
|
|
// Halp21064WritePerformanceCounter(
|
|
// 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(Halp21064WritePerformanceCounter)
|
|
|
|
call_pal wrperfmon // write the counter
|
|
|
|
ret zero, (ra) // return
|
|
|
|
.end Halp21064WritePerformanceCounter
|
|
|
|
//++
|
|
//
|
|
// VOID
|
|
// Halp21064ClearLockRegister(
|
|
// PVOID LockAddress
|
|
// )
|
|
//
|
|
// Routine Description:
|
|
//
|
|
// This function is called on every interrupt to clear the lock bit.
|
|
//
|
|
// Arguments:
|
|
//
|
|
// ClearLockAddress(a0) - Address in which to perform the conditional store.
|
|
//
|
|
// Return Value:
|
|
//
|
|
// None.
|
|
//
|
|
//--
|
|
|
|
LEAF_ENTRY(Halp21064ClearLockRegister)
|
|
|
|
mb // Force all previous write off chip
|
|
stl_c zero, 0x0(a0) // Clear the lock register
|
|
mb // Force the write to clear the lock register off chip
|
|
ret zero, (ra) // return
|
|
|
|
.end Halp21064ClearLockRegister
|
|
|
|
|