diff options
Diffstat (limited to 'private/ntos/nthals/halntp/mips/x4clock.s')
-rw-r--r-- | private/ntos/nthals/halntp/mips/x4clock.s | 338 |
1 files changed, 338 insertions, 0 deletions
diff --git a/private/ntos/nthals/halntp/mips/x4clock.s b/private/ntos/nthals/halntp/mips/x4clock.s new file mode 100644 index 000000000..b40d0e102 --- /dev/null +++ b/private/ntos/nthals/halntp/mips/x4clock.s @@ -0,0 +1,338 @@ + +// TITLE("Interval and Profile Clock Interrupts") +//++ +// +// Copyright (c) 1991-1993 Microsoft Corporation +// +// Module Name: +// +// x4clock.s +// +// Abstract: +// +// This module implements the code necessary to field and process the +// interval and profile clock interrupts on a MIPS R4000 system. +// +//-- + +#include "halmips.h" +#include "faldef.h" + + + + SBTTL("System Clock Interrupt - Processor 0") +//++ +// +// Routine Description: +// +// This routine is entered as the result of an interrupt generated by +// the interval timer. Its function is to acknowledge the interrupt and +// transfer control to the standard system routine to update the system +// time and the execution time of the current thread and process. +// +// Arguments: +// +// s8 - Supplies a pointer to a trap frame. +// +// Return Value: +// +// None. +// +//-- + + .struct 0 +CiArgs: .space 4 * 4 // saved arguments + .space 3 * 4 // fill +CiRa: .space 4 // saved return address +CiFrameLength: // + + NESTED_ENTRY(HalpClockInterrupt0, CiFrameLength, zero) + + subu sp,sp,CiFrameLength // allocate stack frame + sw ra,CiRa(sp) // save return address + + PROLOGUE_END + + .set noreorder + + // + // Clear Timer interrupt by reading + // TimerIntAck register in PMP chip + // only if this is PMP_V3 or later. + // NOTE: There are NO PMP_V1 in existence, + // therefore only checking that PMP_V2 + // or NOT PMP_V2. + // + la t0, HalpPmpRevision + lw t1, 0(t0) + li t2, 2 + beq t1, t2, 2f + nop + + lw t0, HalpPmpTimerIntAck + lw t0, 0(t0) + +2: + + .set reorder + + move a0,s8 // set address of trap frame + lw a1,HalpCurrentTimeIncrement // set current time increment + lw t0,__imp_KeUpdateSystemTime // update system time + jal t0 // + +// +// At each clock interrupt the next time increment is moved to the current +// time increment to "pipeline" the update of the current increment at the +// correct time. If the next interval count is nonzero, then the new time +// increment is moved to the next time increment and the next interval count +// register is loaded with the specified interval count minus one (i.e., ms). +// + + lw t0,KdDebuggerEnabled // get address of debugger enable + lw t1,HalpNextIntervalCount // get next interval count + lw t2,HalpNextTimeIncrement // get the next increment value + lbu t0,0(t0) // get debugger enable flag + lw t3,HalpNewTimeIncrement // get new new time increment value + lw ra,CiRa(sp) // restore return address + or t4,t1,t0 // set interval count or debugger? + sw t2,HalpCurrentTimeIncrement // set current increment value + bne zero,t4,20f // if ne, interval change or debugger + addu sp,sp,CiFrameLength // deallocate stack frame + j ra // return +// +// The interval count must be changed or the debugger is enabled. +// + +20: + + beq zero,t1,30f // if eq, not interval count change + sw zero,HalpNextIntervalCount // clear next interval count + + .set noreorder + + // + // Determine which version of + // the PMP we have so we can + // update the correct counter + // in the 82374. + // + // NOTE: Any machine with PMP_V2 + // uses Counter 0. Any machine + // with PMP_V3 or better uses + // Counter 2. + // + la a0, HalpPmpRevision + lw a0, 0(a0) + li a1, 2 + beq a0, a1, 3f + nop + + // + // Set next interval count for + // Timer 1, Counter 2 + // + lw a0, HalpEisaControlBase + li a2, 0xB6 // Counter2, r/w LSB then MSB, Mode 3 + sb a2, 0x43(a0) + sb t1, 0x42(a0) + srl a1, t1, 8 + b 4f + sb a1, 0x42(a0) + +3: + // + // Set next interval count for + // Timer 1, Counter 0 + // + lw a0, HalpEisaControlBase + li a2, 0x36 // Counter0, r/w LSB then MSB, Mode 3 + sb a2, 0x43(a0) + sb t1, 0x40(a0) + srl a1, t1, 8 + sb a1, 0x40(a0) + +4: + + .set reorder + + sw t3,HalpNextTimeIncrement // set next time increment value +30: beq zero,t0,40f // if eq, debugger not enabled + jal KdPollBreakIn // check if breakin is requested + beq zero,v0,40f // if eq, no breakin requested + li a0,DBG_STATUS_CONTROL_C // break in and send + jal DbgBreakPointWithStatus // status to debugger +40: lw ra,CiRa(sp) // restore return address + addu sp,sp,CiFrameLength // deallocate stack frame + j ra // return + + .end HalpClockInterrupt0 + + + + SBTTL("System Clock Interrupt - Processor N") +//++ +// +// Routine Description: +// +// This routine is entered as the result of an interrupt generated by +// the interval timer. Its function is to acknowledge the interrupt +// and transfer control to the standard system routine to update the +// execution time of the current thread and process. +// +// Arguments: +// +// s8 - Supplies a pointer to a trap frame. +// +// Return Value: +// +// None. +// +//-- + + LEAF_ENTRY(HalpClockInterrupt1) + + // + // clear Timer interrupt by reading + // TimerIntAck register in PMP chip + // only if this is not the first + // version of the PMP chip. + // + lw t0, HalpPmpTimerIntAckProcB + lw t0, 0(t0) + + move a0,s8 // set address of trap frame + lw t1,__imp_KeUpdateRunTime // update system runtime + j t1 + + + + .end HalpClockInterrupt1 + + SBTTL("Profile Clock Interrupt") +//++ +// +// Routine Description: +// +// This routine is entered as the result of an interrupt generated by the +// profile clock. Its function is to acknowledge the profile interrupt, +// compute the next compare value, update the performance counter, and +// transfer control to the standard system routine to process any active +// profiles. +// +// Arguments: +// +// s8 - Supplies a pointer to a trap frame. +// +// Return Value: +// +// None. +// +//-- + + LEAF_ENTRY(HalpProfileInterrupt) + + .set noreorder + .set noat + mfc0 t1,count // get current count value + mfc0 t0,compare // get current comparison value + addu t1,t1,8 // factor in lost cycles + subu t1,t1,t0 // compute initial count value + mtc0 t0,compare // dismiss interrupt + mtc0 t1,count // set new count register value + .set at + .set reorder + + lw t1,KiPcr + PcPrcb(zero) // get current processor block address + la t2,HalpPerformanceCounter // get performance counter address + lbu t1,PbNumber(t1) // get processor number + sll t1,t1,3 // compute address of performance count + addu t1,t1,t2 // + lw t2,LiLowPart(t1) // get low part of performance count + lw t3,LiHighPart(t1) // get high part of performance count + addu t2,t2,t0 // update low part of performance count + sw t2,LiLowPart(t1) // store low part of performance count + sltu t4,t2,t0 // generate carry into high part + addu t3,t3,t4 // update high part of performance count + sw t3,LiHighPart(t1) // store high part of performance count + move a0,s8 // set address of trap frame + lw t4,__imp_KeProfileInterrupt // process profile interrupt + j t4 // + + .end HalpProfileInterrupt + + SBTTL("Read Count Register") +//++ +// +// ULONG +// HalpReadCountRegister ( +// VOID +// ); +// +// Routine Description: +// +// This routine reads the current value of the count register and +// returns the value. +// +// Arguments: +// +// None. +// +// Return Value: +// +// Current value of the count register. +// +//-- + + LEAF_ENTRY(HalpReadCountRegister) + + .set noreorder + .set noat + mfc0 v0,count // get count register value + .set at + .set reorder + + j ra // return + + .end HalpReadCountRegister + + SBTTL("Write Compare Register And Clear") +//++ +// +// ULONG +// HalpWriteCompareRegisterAndClear ( +// IN ULONG Value +// ); +// +// Routine Description: +// +// This routine reads the current value of the count register, writes +// the value of the compare register, clears the count register, and +// returns the previous value of the count register. +// +// Arguments: +// +// Value - Supplies the value written to the compare register. +// +// Return Value: +// +// Previous value of the count register. +// +//-- + + LEAF_ENTRY(HalpWriteCompareRegisterAndClear) + + .set noreorder + .set noat + mfc0 v0,count // get count register value + mtc0 a0,compare // set compare register value + li t0,7 // set lost cycle count + mtc0 t0,count // set count register to zero + .set at + .set reorder + + j ra // return + + .end HalpWriteCompareRegisterAndClear + + |