diff options
Diffstat (limited to 'private/ntos/nthals/halflex/alpha/ev4ints.s')
-rw-r--r-- | private/ntos/nthals/halflex/alpha/ev4ints.s | 300 |
1 files changed, 300 insertions, 0 deletions
diff --git a/private/ntos/nthals/halflex/alpha/ev4ints.s b/private/ntos/nthals/halflex/alpha/ev4ints.s new file mode 100644 index 000000000..08fdaadc0 --- /dev/null +++ b/private/ntos/nthals/halflex/alpha/ev4ints.s @@ -0,0 +1,300 @@ +//++ +// +// 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 + + |