OvmfPkg: End timer interrupt later to avoid stack overflow under load

RestoreTPL called while at TPL_HIGH_LEVEL unconditionally enables
interrupts even if called in interrupt handler. That opens a window while
interrupt is not completely handled but another interrupt could be
accepted.

If a VM starts on a heavily loaded host hundreds of periodic timer
interrupts might be queued while vCPU is descheduled (the behavior is
typical for a Xen host). The next time vCPU is scheduled again all of them
get delivered back to back causing OVMF to accept each one without
finishing a previous one and cleaning up the stack. That quickly results
in stack overflow and a triple fault.

Fix it by postponing sending EOI until we finished processing the current
tick giving interrupt handler opportunity to clean up the stack before
accepting the next tick.

Signed-off-by: Igor Druzhinin <igor.druzhinin@citrix.com>
Message-Id: <1592275782-9369-1-git-send-email-igor.druzhinin@citrix.com>
Reviewed-by: Paolo Bonzini <pbonzini@redhat.com>
Ref: https://bugzilla.tianocore.org/show_bug.cgi?id=2815
Acked-by: Laszlo Ersek <lersek@redhat.com>
[lersek@redhat.com: add BZ ref; rewrap msg to silence PatchCheck.py]
This commit is contained in:
Igor Druzhinin 2020-06-16 03:49:42 +01:00 committed by mergify[bot]
parent 3a9f932d80
commit 239b50a863
2 changed files with 6 additions and 4 deletions

View File

@ -79,8 +79,6 @@ TimerInterruptHandler (
OriginalTPL = gBS->RaiseTPL (TPL_HIGH_LEVEL);
mLegacy8259->EndOfInterrupt (mLegacy8259, Efi8259Irq0);
if (mTimerNotifyFunction != NULL) {
//
// @bug : This does not handle missed timer interrupts
@ -89,6 +87,9 @@ TimerInterruptHandler (
}
gBS->RestoreTPL (OriginalTPL);
DisableInterrupts ();
mLegacy8259->EndOfInterrupt (mLegacy8259, Efi8259Irq0);
}
/**

View File

@ -61,8 +61,6 @@ TimerInterruptHandler (
OriginalTPL = gBS->RaiseTPL (TPL_HIGH_LEVEL);
SendApicEoi();
if (mTimerNotifyFunction != NULL) {
//
// @bug : This does not handle missed timer interrupts
@ -71,6 +69,9 @@ TimerInterruptHandler (
}
gBS->RestoreTPL (OriginalTPL);
DisableInterrupts ();
SendApicEoi ();
}
/**