From 65d69d33da445afc7ff56857af1881cf73666be4 Mon Sep 17 00:00:00 2001 From: Ross Lagerwall Date: Tue, 30 Jan 2024 10:52:29 +0000 Subject: [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 Modified-by: Michael Brown Signed-off-by: Michael Brown --- src/arch/arm/interface/efi/efiarm_nap.c | 6 +++++- src/arch/loong64/interface/efi/efiloong64_nap.c | 6 +++++- 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 9ed638e9a..fba7a5d82 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 5cd1c1b94..0a7609783 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 3ebf0bd68..296876b85 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 ); -- cgit