]> git.ipfire.org Git - thirdparty/ipxe.git/commitdiff
[efi] Fix hang during ExitBootServices() 1136/head
authorRoss Lagerwall <ross.lagerwall@citrix.com>
Tue, 30 Jan 2024 10:52:29 +0000 (10:52 +0000)
committerMichael Brown <mcb30@ipxe.org>
Wed, 31 Jan 2024 13:23:56 +0000 (13:23 +0000)
When ExitBootServices() invokes efi_shutdown_hook(), there may be
nothing to generate an interrupt since the timer is disabled in the
first step of ExitBootServices().  Additionally, for VMs OVMF masks
everything from the PIC (except the timer) by default.  This means
that calling cpu_nap() may hang indefinitely.  This was seen in
practice in netfront_reset() when running in a VM on XenServer.

Fix this by skipping the halt if an EFI shutdown is in progress.

Signed-off-by: Ross Lagerwall <ross.lagerwall@citrix.com>
Modified-by: Michael Brown <mcb30@ipxe.org>
Signed-off-by: Michael Brown <mcb30@ipxe.org>
src/arch/arm/interface/efi/efiarm_nap.c
src/arch/loong64/interface/efi/efiloong64_nap.c
src/arch/x86/interface/efi/efix86_nap.c

index 9ed638e9a6c7510c86458cec7c2314a51189f620..fba7a5d82a6a926cf8d0d95c88be124426168a5d 100644 (file)
@@ -46,8 +46,12 @@ static void efiarm_cpu_nap ( void ) {
         * The EFI shell doesn't seem to bother sleeping the CPU; it
         * just sits there idly burning power.
         *
+        * If a shutdown is in progess, there may be nothing to
+        * generate an interrupt since the timer is disabled in the
+        * first step of ExitBootServices().
         */
-       __asm__ __volatile__ ( "wfi" );
+       if ( ! efi_shutdown_in_progress )
+               __asm__ __volatile__ ( "wfi" );
 }
 
 PROVIDE_NAP ( efiarm, cpu_nap, efiarm_cpu_nap );
index 5cd1c1b94698d640ec82324076a1f3678832f220..0a7609783f81c24575d597595b5e1fa38d3d5cd3 100644 (file)
@@ -46,8 +46,12 @@ static void efiloong64_cpu_nap ( void ) {
         * The EFI shell doesn't seem to bother sleeping the CPU; it
         * just sits there idly burning power.
         *
+        * If a shutdown is in progess, there may be nothing to
+        * generate an interrupt since the timer is disabled in the
+        * first step of ExitBootServices().
         */
-       __asm__ __volatile__ ( "idle 0" );
+       if ( ! efi_shutdown_in_progress )
+               __asm__ __volatile__ ( "idle 0" );
 }
 
 PROVIDE_NAP ( efiloong64, cpu_nap, efiloong64_cpu_nap );
index 3ebf0bd68fcf29a5cba7cd4b6a6b362851ab3507..296876b858ed9dae65ccea3e52417b3d06a8e441 100644 (file)
@@ -46,8 +46,12 @@ static void efix86_cpu_nap ( void ) {
         * The EFI shell doesn't seem to bother sleeping the CPU; it
         * just sits there idly burning power.
         *
+        * If a shutdown is in progess, there may be nothing to
+        * generate an interrupt since the timer is disabled in the
+        * first step of ExitBootServices().
         */
-       __asm__ __volatile__ ( "hlt" );
+       if ( ! efi_shutdown_in_progress )
+               __asm__ __volatile__ ( "hlt" );
 }
 
 PROVIDE_NAP ( efix86, cpu_nap, efix86_cpu_nap );