From ac5c5785b1d0bf6ffbe2e803d7118f3b5a793986 Mon Sep 17 00:00:00 2001 From: Laszlo Ersek Date: Thu, 5 Feb 2015 17:53:53 +0100 Subject: ArmPkg: TimerDxe: smack down spurious timer interrupt (RHELSA hack) Message-id: <1423155233-22668-2-git-send-email-lersek@redhat.com> Patchwork-id: 63732 O-Subject: [RHELSA AAVMF PATCH 1/1] ArmPkg: TimerDxe: smack down spurious timer interrupt (RHELSA hack) Bugzilla: 1188054 Acked-by: Miroslav Rezanina Acked-by: wei@redhat.com Acked-by: Andrew Jones When an aarch64 KVM guest is rebooted with the UEFI shell command "reset -c", the instance of AAVMF that runs after the reboot hangs in the timer driver. We tracked this issue unto a virtual timer interrupt that remains stuck / asserted across the reboot for some reason, and is delivered to the handler function in TimerDxe *before* TimerDxe is done setting up data for the handler and unmasks the interrupt. This happens to cause an infinite loop in the handler. The above situation should never emerge (an interrupt, stuck or not, should never be delivered while it is masked). This could be a KVM bug -- which we track with clone bug 1189429 and reported privately to ARM & Linaro people --, but until the root cause gets sorted out, we need to move forward with AAVMF. Attempts to clear interrupt lines up-front have borne no fruit. Hence we enable the handler to cope with a spurious interrupt. Downstream only. Should be reverted when 1189429 is fixed. Signed-off-by: Laszlo Ersek --- ArmPkg/Drivers/TimerDxe/TimerDxe.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/ArmPkg/Drivers/TimerDxe/TimerDxe.c b/ArmPkg/Drivers/TimerDxe/TimerDxe.c index 1169d42..6a8c312 100644 --- a/ArmPkg/Drivers/TimerDxe/TimerDxe.c +++ b/ArmPkg/Drivers/TimerDxe/TimerDxe.c @@ -313,6 +313,12 @@ TimerInterruptHandler ( // Signal end of interrupt early to help avoid losing subsequent ticks from long duration handlers gInterrupt->EndOfInterrupt (gInterrupt, Source); + if (mTimerPeriod == 0) { + DEBUG ((EFI_D_WARN, "%a: hack: this should never happen; dodged spurious" + " interrupt 0x%Lx\n", __FUNCTION__, (UINT64)Source)); + goto Done; + } + if (mTimerNotifyFunction) { mTimerNotifyFunction (mTimerPeriod * mElapsedPeriod); } @@ -340,6 +346,7 @@ TimerInterruptHandler ( ArmGenericTimerEnableTimer (); } +Done: // Enable timer interrupts gInterrupt->EnableInterruptSource (gInterrupt, Source); -- 1.8.3.1