--- /dev/null
+/** @file\r
+ Handle raising and lowering TPL from within nested interrupt handlers.\r
+\r
+ Allows interrupt handlers to safely raise and lower the TPL to\r
+ dispatch event notifications, correctly allowing for nested\r
+ interrupts to occur without risking stack exhaustion.\r
+\r
+ Copyright (C) 2022, Fen Systems Ltd.\r
+\r
+ SPDX-License-Identifier: BSD-2-Clause-Patent\r
+**/\r
+\r
+#ifndef __NESTED_INTERRUPT_TPL_LIB__\r
+#define __NESTED_INTERRUPT_TPL_LIB__\r
+\r
+#include <Uefi/UefiBaseType.h>\r
+#include <Uefi/UefiSpec.h>\r
+#include <Protocol/DebugSupport.h>\r
+\r
+///\r
+/// State shared between all invocations of a nested interrupt handler.\r
+///\r
+typedef struct {\r
+ ///\r
+ /// Highest TPL that is currently the target of a call to\r
+ /// RestoreTPL() by an instance of this interrupt handler.\r
+ ///\r
+ EFI_TPL InProgressRestoreTPL;\r
+ ///\r
+ /// Flag used to defer a call to RestoreTPL() from an inner instance\r
+ /// of the interrupt handler to an outer instance of the same\r
+ /// interrupt handler.\r
+ ///\r
+ BOOLEAN DeferredRestoreTPL;\r
+} NESTED_INTERRUPT_STATE;\r
+\r
+/**\r
+ Raise the task priority level to TPL_HIGH_LEVEL.\r
+\r
+ @param None.\r
+\r
+ @return The task priority level at which the interrupt occurred.\r
+**/\r
+EFI_TPL\r
+EFIAPI\r
+NestedInterruptRaiseTPL (\r
+ VOID\r
+ );\r
+\r
+/**\r
+ Lower the task priority back to the value at which the interrupt\r
+ occurred.\r
+\r
+ This is unfortunately messy. UEFI requires us to support nested\r
+ interrupts, but provides no way for an interrupt handler to call\r
+ RestoreTPL() without implicitly re-enabling interrupts. In a\r
+ virtual machine, it is possible for a large burst of interrupts to\r
+ arrive. We must prevent such a burst from leading to stack\r
+ exhaustion, while continuing to allow nested interrupts to occur.\r
+\r
+ Since nested interrupts are permitted, an interrupt handler may be\r
+ invoked as an inner interrupt handler while an outer instance of the\r
+ same interrupt handler is still inside its call to RestoreTPL().\r
+\r
+ To avoid stack exhaustion, this call may therefore (when provably\r
+ safe to do so) defer the actual TPL lowering to be performed by an\r
+ outer instance of the same interrupt handler.\r
+\r
+ @param InterruptedTPL The task priority level at which the interrupt\r
+ occurred, as previously returned from\r
+ NestedInterruptRaiseTPL().\r
+\r
+ @param SystemContext A pointer to the system context when the\r
+ interrupt occurred.\r
+\r
+ @param IsrState A pointer to the state shared between all\r
+ invocations of the nested interrupt handler.\r
+**/\r
+VOID\r
+EFIAPI\r
+NestedInterruptRestoreTPL (\r
+ IN EFI_TPL InterruptedTPL,\r
+ IN OUT EFI_SYSTEM_CONTEXT SystemContext,\r
+ IN OUT NESTED_INTERRUPT_STATE *IsrState\r
+ );\r
+\r
+#endif // __NESTED_INTERRUPT_TPL_LIB__\r