diff options
author | Ross Lagerwall <ross.lagerwall@citrix.com> | 2024-01-30 10:52:29 +0000 |
---|---|---|
committer | Michael Brown <mcb30@ipxe.org> | 2024-01-31 13:23:56 +0000 |
commit | 65d69d33da445afc7ff56857af1881cf73666be4 (patch) | |
tree | 5d5eab26731328a76eabac02bb086fa99f7aea6d /src | |
parent | 963ec1c4f379a49cf37d01472a770fff8e47470c (diff) | |
download | ipxe-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>
Diffstat (limited to 'src')
-rw-r--r-- | src/arch/arm/interface/efi/efiarm_nap.c | 6 | ||||
-rw-r--r-- | src/arch/loong64/interface/efi/efiloong64_nap.c | 6 | ||||
-rw-r--r-- | src/arch/x86/interface/efi/efix86_nap.c | 6 |
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 ); |