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.
325 lines
11 KiB
325 lines
11 KiB
//#pragma comment(exestr, "$Header: /usr4/winnt/SOURCES/ddk35/src/hal/halsni/mips/RCS/x4clock.s,v 1.4 1995/02/13 12:54:07 flo Exp $")
|
|
|
|
// TITLE("Interval and Profile Clock Interrupts")
|
|
//++
|
|
//
|
|
// Copyright (c) 1991 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.
|
|
//
|
|
// Environment:
|
|
//
|
|
// Kernel mode only.
|
|
//
|
|
//
|
|
//--
|
|
|
|
#include "halmips.h"
|
|
#include "SNIdef.h"
|
|
|
|
|
|
SBTTL("System Clock Interrupt")
|
|
//++
|
|
//
|
|
// 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(HalpClockInterrupt, CiFrameLength, zero)
|
|
|
|
|
|
subu sp,sp,CiFrameLength // allocate stack frame
|
|
sw ra,CiRa(sp) // save return address
|
|
|
|
PROLOGUE_END
|
|
|
|
move a0,s8 // set address of trap frame
|
|
lw a1,HalpCurrentTimeIncrement
|
|
lw t0,__imp_KeUpdateSystemTime // update system time
|
|
jal t0 //
|
|
|
|
#if DBG
|
|
#else
|
|
|
|
//
|
|
// we use this only when we have the machine up and running ...
|
|
// LED's can show us something, what we do not see in the debugger
|
|
//
|
|
|
|
la t0,HalpLedRegister // get current Value of LED Register
|
|
lw a0,0(t0)
|
|
addu a0,a0,1 // increment
|
|
sw a0,0(t0) // store and
|
|
la t0, HalpLedAddress // get address of the variable
|
|
lw t0,0(t0) // get value
|
|
sb a0,0(t0) // display LSByte (set the LED)
|
|
#endif
|
|
|
|
//
|
|
// 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 new time increment is nonzero, then the new time
|
|
// increment is moved to the next time increment and the timer is reprogramed
|
|
//
|
|
|
|
lw t0,KdDebuggerEnabled // get address of debugger enable
|
|
lw t1,HalpNewTimeIncrement // get new time increment
|
|
lw t2,HalpNextTimeIncrement // get the next increment value
|
|
lbu t0,0(t0) // get debugger enable flag
|
|
lw ra,CiRa(sp) // restore return address
|
|
or t4,t1,t0 // new interval count or debugger?
|
|
sw t2,HalpCurrentTimeIncrement // pipeline current increment value
|
|
bne zero,t4,10f // 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.
|
|
//
|
|
|
|
10: sw zero,HalpNewTimeIncrement // clear new time increment
|
|
beq zero,t1,15f // if eq, not interval count change
|
|
sw t1,HalpNextTimeIncrement // set next time increment value
|
|
move a0,t1 // prepare to call HalpProgramIntervalTimer
|
|
jal HalpProgramIntervalTimer // program timer chip ...
|
|
15: beq zero,t0,40f // if eq, debugger not enabled
|
|
//15: beq zero,t0,20f // if eq, debugger not enabled
|
|
jal KdPollBreakIn // check if breakin is requested
|
|
beq zero,v0,40f // if eq, no breakin requested
|
|
// beq zero,v0,20f // if eq, no breakin requested
|
|
li a0,DBG_STATUS_CONTROL_C // break in and send
|
|
jal DbgBreakPointWithStatus // status to debugger
|
|
|
|
//
|
|
// Check if profiling is active and the profile interval has expired.
|
|
//
|
|
//
|
|
//20: la t0,HalpCountCompareInterrupt // profiling via CountCompare ?
|
|
// lb t1,0(t0)
|
|
// bne zero,t1,40f // if set, profiling is done via CountCompare Interrupt
|
|
// lw t0,KiPcr + PcProfileCount(zero) // get remaining profile count
|
|
// li t1,TIME_INCREMENT // get time increment value
|
|
// beq zero,t0,40f // if eq, profiling not enabled
|
|
// subu t0,t0,t1 // subtract time increment from count
|
|
// bgtz t0,30f // if gtz, not end of profile interval
|
|
// move a0,s8 // set address of trap frame
|
|
// jal KeProfileInterrupt // process profile entries
|
|
// lw t0,KiPcr + PcProfileInterval(zero) // get profile interval value
|
|
//30: sw t0,KiPcr + PcProfileCount(zero) // set remaining profile count
|
|
40: lw ra,CiRa(sp) // restore return address
|
|
addu sp,sp,CiFrameLength // deallocate stack frame
|
|
j ra // return
|
|
|
|
.end HalpClockInterrupt
|
|
|
|
SBTTL("System Clock Interrupt - Processor N")
|
|
//++
|
|
//
|
|
// Routine Description:
|
|
//
|
|
// This routine is entered as the result of an interrupt generated by
|
|
// the extra interval timer in the slave processors. Its function is
|
|
// to transfer control to the standard system routine to update the
|
|
// execution time of the current thread and process.
|
|
//
|
|
// Note: We plan to use the extra timer for our MultiProcessor (SNI)Machine
|
|
// MAYBE, if we have arbitrated interrupts, we have to acknowledge
|
|
// this interrupt here and send an message to the other processors
|
|
// (Quadro machine)
|
|
//
|
|
// Arguments:
|
|
//
|
|
// s8 - Supplies a pointer to a trap frame.
|
|
//
|
|
// Return Value:
|
|
//
|
|
// None.
|
|
//
|
|
//--
|
|
|
|
NESTED_ENTRY(HalpClockInterrupt1, CiFrameLength, zero)
|
|
|
|
subu sp,sp,CiFrameLength // allocate stack frame
|
|
sw ra,CiRa(sp) // save return address
|
|
|
|
PROLOGUE_END
|
|
|
|
li t0, RM400_TIMER0_ACK_ADDR // get address of acknowledge register
|
|
sb zero,0(t0) // acknowledge timer interrupt
|
|
jal HalpCheckSpuriousInt
|
|
move a0,s8 // set address of trap frame
|
|
lw t1,__imp_KeUpdateRunTime // update system runtime
|
|
lw ra,CiRa(sp) // restore return address
|
|
addu sp,sp,CiFrameLength // deallocate stack frame
|
|
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.
|
|
//
|
|
//--
|
|
|
|
NESTED_ENTRY(HalpProfileInterrupt, CiFrameLength, zero)
|
|
|
|
subu sp,sp,CiFrameLength // allocate stack frame
|
|
sw ra,CiRa(sp) // save return address
|
|
|
|
PROLOGUE_END
|
|
|
|
.set noreorder
|
|
.set noat
|
|
|
|
jal HalpCheckSpuriousInt
|
|
nop
|
|
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
|
|
|
|
//
|
|
// we prefer the MultiPro version, which also works on UniPro machines
|
|
//
|
|
|
|
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
|
|
lw ra,CiRa(sp) // restore return address
|
|
addu sp,sp,CiFrameLength // deallocate stack frame
|
|
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
|