// 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)