342 lines
6.7 KiB
ArmAsm
342 lines
6.7 KiB
ArmAsm
// 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)
|