audk/OvmfPkg/Include
Michael Brown a24fbd6061 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>
2022-12-23 14:44:48 +00:00
..
Dsc OvmfPkg: move dsc include snippet for Network support to Include/Dsc 2022-12-09 14:07:21 +00:00
Fdf mv OvmfPkg: move fdf include snippets to Include/Fdf 2022-12-09 14:07:21 +00:00
Guid OvmfPkg/AmdSev: expose the SNP reserved pages through configuration table 2021-12-09 06:28:10 +00:00
IndustryStandard OvmfPkg: Update I/O port related to ACPI devices for CloudHv 2022-09-08 00:28:42 +00:00
Library OvmfPkg: Add library to handle TPL from within nested interrupt handlers 2022-12-23 14:44:48 +00:00
Pcd OvmfPkg: Apply uncrustify changes 2021-12-07 17:24:28 +00:00
Ppi OvmfPkg: Add MpInitLibDepLib related PPI/Protocol definitions 2022-05-11 08:40:53 +00:00
Protocol OvmfPkg: Add MpInitLibDepLib related PPI/Protocol definitions 2022-05-11 08:40:53 +00:00
Register OvmfPkg: Apply uncrustify changes 2021-12-07 17:24:28 +00:00
OvmfPlatforms.h OvmfPkg: Handle Cloud Hypervisor host bridge 2021-12-11 14:26:05 +00:00
TdxCommondefs.inc OvmfPkg: Enable APs to accept memory for TDVF 2022-12-21 07:06:17 +00:00
WorkArea.h mv OvmfPkg: move fdf include snippets to Include/Fdf 2022-12-09 14:07:21 +00:00