windows-nt/Source/XPSP1/NT/base/ntos/ke/ia64/irql.s

342 lines
6.7 KiB
ArmAsm
Raw Normal View History

2020-09-26 03:20:57 -05:00
// TITLE("Manipulate Interrupt Request Level")
//++
//
// Module Name:
//
// irql.s
//
// Abstract:
//
// This module implements the code necessary to lower and raise the current
// Interrupt Request Level (IRQL).
//
//
// Author:
//
// William K. Cheung (wcheung) 05-Oct-1995
//
// Environment:
//
// Kernel mode only.
//
// Revision History:
//
// 08-Feb-1996 Updated to EAS2.1
//
//--
#include "ksia64.h"
.file "irql.s"
//
// Globals
//
PublicFunction(KiCheckForSoftwareInterrupt)
//++
//
// VOID
// KiLowerIrqlSpecial (
// KIRQL NewIrql
// )
//
// Routine Description:
//
// This function lowers the current IRQL to the specified value.
// Does not check for software interrupts. For use within the software interupt
// dispatch code.
//
// Arguments:
//
// NewIrql (a0) - Supplies the new IRQL value.
//
// Return Value:
//
// None.
//
// N.B. The IRQL is being lowered. Therefore, it is not necessary to
// do a data serialization after the TPR is updated unless it is
// very critical to accept interrupts of lower priorities as soon
// as possible. The TPR change will take into effect eventually.
//
//--
LEAF_ENTRY(KiLowerIrqlSpecial)
SET_IRQL(a0)
LEAF_RETURN
LEAF_EXIT(KiLowerIrqlSpecial)
//++
//
// VOID
// KiLowerIrqlSoftwareInterruptPending(
// IN TEMP_REG NewIrql
// )
//
// Routine Description:
//
// This function is entered directly from a LEAF function that is
// lowering IRQL before it exits when there is a software interrupt
// pending that will fire as a result of lowering IRQL.
//
// In this special case, we need to promote to a nested entry in
// order to process the simulated interrupt.
//
// Return is directly to the caller of the leaf function.
//
// This routine is entered with interrupts disabled, this is a
// side effect of the code that branched here needing interrupts
// disabled while checking and lowering.
//
// Arguments:
//
// NewIrql - Because we are branched to from a leaf routine,
// the argument must be passed in non-windowed
// register t22 (r31).
//
// Return Value:
//
// None.
//
//--
NESTED_ENTRY(KiLowerIrqlSoftwareInterruptPending)
NESTED_SETUP(0,3,1,0)
PROLOGUE_END
mov out0 = t22
ssm 1 << PSR_I
;;
br.call.spnt brp = KiCheckForSoftwareInterrupt;;
NESTED_RETURN
NESTED_EXIT(KiLowerIrqlSoftwareInterruptPending)
//++
//
// VOID
// KeLowerIrql (
// KIRQL NewIrql
// )
//
// Routine Description:
//
// This function lowers the current IRQL to the specified value.
//
// Arguments:
//
// NewIrql (a0) - Supplies the new IRQL value.
//
// Return Value:
//
// None.
//
// N.B. The IRQL is being lowered. Therefore, it is not necessary to
// do a data serialization after the TPR is updated unless it is
// very critical to accept interrupts of lower priorities as soon
// as possible. The TPR change will take into effect eventually.
//
//--
LEAF_ENTRY(KeLowerIrql)
//
// KIRQL is a byte, extend to 64 bits.
//
zxt1 a0 = a0
;;
//
// If lowering below DISPATCH_LEVEL, check for pending
// software interrupts that could run now.
//
// This needs to be done with interrupts disabled to
// avoid the case where an interrupt is set pending
// while we check but before IRQL is actually lowered.
//
cmp.gtu pt0 = DISPATCH_LEVEL, a0
movl t21 = KiPcr+PcSoftwareInterruptPending;;
(pt0) rsm 1 << PSR_I
(pt0) ld2 t21 = [t21]
mov t22 = a0;;
(pt0) cmp.ltu.unc pt1, pt2 = a0, t21
//
// If a software interrupt would fire now, branch directly
// to KiLowerIrqlSoftwareInterruptPending which will promote
// to a NESTED routine, handle the interrupt, lower IRQL and
// return directly to the caller.
//
(pt1) br.spnt KiLowerIrqlSoftwareInterruptPending
//
// Didn't have an interrupt pending, lower IRQL and return.
//
SET_IRQL(a0)
//
// Enable interrupts and return.
//
ssm 1 << PSR_I
LEAF_RETURN
LEAF_EXIT(KeLowerIrql)
//++
//
// VOID
// KeRaiseIrql (
// KIRQL NewIrql,
// PKIRQL OldIrql
// )
//
// Routine Description:
//
// This function raises the current IRQL to the specified value and returns
// the old IRQL value.
//
// Arguments:
//
// NewIrql (a0) - Supplies the new IRQL value.
//
// OldIrql (a1) - Supplies a pointer to a variable that recieves the old
// IRQL value.
//
// Return Value:
//
// None.
//
//--
LEAF_ENTRY(KeRaiseIrql)
//
// Register aliases
//
rOldIrql = t3
GET_IRQL (rOldIrql)
SET_IRQL (a0) // Raise IRQL
;;
st1 [a1] = rOldIrql // return old IRQL value
LEAF_RETURN
LEAF_EXIT(KeRaiseIrql)
//++
//
// KIRQL
// KfRaiseIrql (
// KIRQL NewIrql
// )
//
// Routine Description:
//
// This function raises the current IRQL to the specified value and returns
// the old IRQL value.
//
// Arguments:
//
// NewIrql (a0) - Supplies the new IRQL value.
//
// Return Value:
//
// Old Irql value.
//
//--
LEAF_ENTRY(KfRaiseIrql)
GET_IRQL (r8) // Put old IRQL in return register.
SET_IRQL (a0) // Raise IRQL
LEAF_RETURN
LEAF_EXIT(KfRaiseIrql)
//++
//
// KIRQL
// KeRaiseIrqlToDpcLevel (
// VOID
// )
//
// Routine Description:
//
// This function raises the current IRQL to DISPATCH_LEVEL and returns
// the old IRQL value.
//
// Arguments:
//
// None.
//
// Return Value:
//
// Old IRQL value
//
//--
LEAF_ENTRY(KeRaiseIrqlToDpcLevel)
//
// Register aliases
//
rNewIrql = t0
mov rNewIrql = DISPATCH_LEVEL
GET_IRQL(v0)
;;
SET_IRQL (rNewIrql) // Raise IRQL
LEAF_RETURN
LEAF_EXIT(KeRaiseIrqlToDpcLevel)
//++
//
// KIRQL
// KeRaiseIrqlToSynchLevel (
// VOID
// )
//
// Routine Description:
//
// This function raises the current IRQL to SYNCH_LEVEL and returns
// the old IRQL value.
//
// Arguments:
//
// None.
//
// Return Value:
//
// Old IRQL value
//
//--
LEAF_ENTRY(KeRaiseIrqlToSynchLevel)
//
// Register aliases
//
rNewIrql = t0
mov rNewIrql = SYNCH_LEVEL
GET_IRQL(v0)
;;
SET_IRQL (rNewIrql) // Raise IRQL
LEAF_RETURN
LEAF_EXIT(KeRaiseIrqlToSynchLevel)