aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRoss Lagerwall <ross.lagerwall@citrix.com>2024-01-30 10:52:29 +0000
committerMichael Brown <mcb30@ipxe.org>2024-01-31 13:23:56 +0000
commit65d69d33da445afc7ff56857af1881cf73666be4 (patch)
tree5d5eab26731328a76eabac02bb086fa99f7aea6d
parent963ec1c4f379a49cf37d01472a770fff8e47470c (diff)
downloadipxe-65d69d33da445afc7ff56857af1881cf73666be4.zip
ipxe-65d69d33da445afc7ff56857af1881cf73666be4.tar.gz
ipxe-65d69d33da445afc7ff56857af1881cf73666be4.tar.bz2
[efi] Fix hang during ExitBootServices()
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>
-rw-r--r--src/arch/arm/interface/efi/efiarm_nap.c6
-rw-r--r--src/arch/loong64/interface/efi/efiloong64_nap.c6
-rw-r--r--src/arch/x86/interface/efi/efix86_nap.c6
3 files changed, 15 insertions, 3 deletions
diff --git a/src/arch/arm/interface/efi/efiarm_nap.c b/src/arch/arm/interface/efi/efiarm_nap.c
index 9ed638e..fba7a5d 100644
--- a/src/arch/arm/interface/efi/efiarm_nap.c
+++ b/src/arch/arm/interface/efi/efiarm_nap.c
@@ -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 );
diff --git a/src/arch/loong64/interface/efi/efiloong64_nap.c b/src/arch/loong64/interface/efi/efiloong64_nap.c
index 5cd1c1b..0a76097 100644
--- a/src/arch/loong64/interface/efi/efiloong64_nap.c
+++ b/src/arch/loong64/interface/efi/efiloong64_nap.c
@@ -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 );
diff --git a/src/arch/x86/interface/efi/efix86_nap.c b/src/arch/x86/interface/efi/efix86_nap.c
index 3ebf0bd..296876b 100644
--- a/src/arch/x86/interface/efi/efix86_nap.c
+++ b/src/arch/x86/interface/efi/efix86_nap.c
@@ -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 );