summaryrefslogtreecommitdiffstats
path: root/OvmfPkg/OvmfPkg.dec
diff options
context:
space:
mode:
authorMichael Brown <mcb30@ipxe.org>2022-12-09 10:20:24 +0000
committermergify[bot] <37929162+mergify[bot]@users.noreply.github.com>2022-12-23 14:44:48 +0000
commita24fbd6061254ca74d6c6ed953dec6f796a45c76 (patch)
treec9631feec0d886192e3864c0a8bbd63695e3b331 /OvmfPkg/OvmfPkg.dec
parent9bf473da4c1d6d3656beca3a914861dcd1fe8a25 (diff)
downloadedk2-a24fbd6061254ca74d6c6ed953dec6f796a45c76.tar.gz
edk2-a24fbd6061254ca74d6c6ed953dec6f796a45c76.tar.bz2
edk2-a24fbd6061254ca74d6c6ed953dec6f796a45c76.zip
OvmfPkg: Add library to handle TPL from within nested interrupt handlers
UEFI requires us to support nested interrupts, but provides no way for an interrupt handler to call RestoreTPL() without implicitly re-enabling interrupts. In a virtual machine, it is possible for a large burst of interrupts to arrive. We must prevent such a burst from leading to stack underrun, while continuing to allow nested interrupts to occur. This can be achieved by allowing, when provably safe to do so, an inner interrupt handler to return from the interrupt without restoring the TPL and with interrupts remaining disabled after IRET, with the deferred call to RestoreTPL() then being issued from the outer interrupt handler. This is necessarily messy and involves direct manipulation of the interrupt stack frame, and so should not be implemented as open-coded logic within each interrupt handler. Add the Nested Interrupt TPL Library (NestedInterruptTplLib) to provide helper functions that can be used by nested interrupt handlers in place of RaiseTPL()/RestoreTPL(). Example call tree for a timer interrupt occurring at TPL_APPLICATION with a nested timer interrupt that makes its own call to RestoreTPL(): outer TimerInterruptHandler() InterruptedTPL == TPL_APPLICATION ... IsrState->InProgressRestoreTPL = TPL_APPLICATION; gBS->RestoreTPL (TPL_APPLICATION); EnableInterrupts(); dispatch a TPL_CALLBACK event gEfiCurrentTpl = TPL_CALLBACK; nested timer interrupt occurs inner TimerInterruptHandler() InterruptedTPL == TPL_CALLBACK ... IsrState->InProgressRestoreTPL = TPL_CALLBACK; gBS->RestoreTPL (TPL_CALLBACK); EnableInterrupts(); DisableInterrupts(); IsrState->InProgressRestoreTPL = TPL_APPLICATION; IRET re-enables interrupts ... finish dispatching TPL_CALLBACK events ... gEfiCurrentTpl = TPL_APPLICATION; DisableInterrupts(); IsrState->InProgressRestoreTPL = 0; sees IsrState->DeferredRestoreTPL == FALSE and returns IRET re-enables interrupts Example call tree for a timer interrupt occurring at TPL_APPLICATION with a nested timer interrupt that defers its call to RestoreTPL() to the outer instance of the interrupt handler: outer TimerInterruptHandler() InterruptedTPL == TPL_APPLICATION ... IsrState->InProgressRestoreTPL = TPL_APPLICATION; gBS->RestoreTPL (TPL_APPLICATION); EnableInterrupts(); dispatch a TPL_CALLBACK event ... finish dispatching TPL_CALLBACK events ... gEfiCurrentTpl = TPL_APPLICATION; nested timer interrupt occurs inner TimerInterruptHandler() InterruptedTPL == TPL_APPLICATION; ... sees InterruptedTPL == IsrState->InProgressRestoreTPL IsrState->DeferredRestoreTPL = TRUE; DisableInterruptsOnIret(); IRET returns without re-enabling interrupts DisableInterrupts(); IsrState->InProgressRestoreTPL = 0; sees IsrState->DeferredRestoreTPL == TRUE and loops IsrState->InProgressRestoreTPL = TPL_APPLICATION; gBS->RestoreTPL (TPL_APPLICATION); <-- deferred call EnableInterrupts(); DisableInterrupts(); IsrState->InProgressRestoreTPL = 0; sees IsrState->DeferredRestoreTPL == FALSE and returns IRET re-enables interrupts Cc: Paolo Bonzini <pbonzini@redhat.com> Ref: https://bugzilla.tianocore.org/show_bug.cgi?id=4162 Signed-off-by: Michael Brown <mcb30@ipxe.org> Acked-by: Laszlo Ersek <lersek@redhat.com>
Diffstat (limited to 'OvmfPkg/OvmfPkg.dec')
-rw-r--r--OvmfPkg/OvmfPkg.dec4
1 files changed, 4 insertions, 0 deletions
diff --git a/OvmfPkg/OvmfPkg.dec b/OvmfPkg/OvmfPkg.dec
index a350bb8f84..693925a1dc 100644
--- a/OvmfPkg/OvmfPkg.dec
+++ b/OvmfPkg/OvmfPkg.dec
@@ -38,6 +38,10 @@
#
MemEncryptTdxLib|Include/Library/MemEncryptTdxLib.h
+ ## @libraryclass Handle TPL changes within nested interrupt handlers
+ #
+ NestedInterruptTplLib|Include/Library/NestedInterruptTplLib.h
+
## @libraryclass Save and restore variables using a file
#
NvVarsFileLib|Include/Library/NvVarsFileLib.h