* OVMF is crashing for me in master @ 2019-10-10 21:12 Andrew Fish 2019-10-11 1:19 ` [edk2-devel] " Liming Gao 0 siblings, 1 reply; 10+ messages in thread From: Andrew Fish @ 2019-10-10 21:12 UTC (permalink / raw) To: devel, Pete Batard [-- Attachment #1: Type: text/plain, Size: 7568 bytes --] This is my flavor of OVMF: build -p OvmfPkg/OvmfPkgX64.dsc -a X64 -t XCODE5 It looks like I took an exception? Is it expected that an unhandled exception just hang in a dead loop? I would have expected some serial output about the failure? Looks like a divide by zero exception. The exception context has PC and FP so I can manually walk the stack. Yikes I see PlatformBootManagerWaitCallback() will fault if PcdPlatformBootTimeOut is zero? /Volumes/Case/UDK2018(master)>git grep PcdPlatformBootTimeOut -- *.dsc ArmVirtPkg/ArmVirtQemu.dsc:194: gEfiMdePkgTokenSpaceGuid.PcdPlatformBootTimeOut|3 ArmVirtPkg/ArmVirtQemuKernel.dsc:191: gEfiMdePkgTokenSpaceGuid.PcdPlatformBootTimeOut|3 ArmVirtPkg/ArmVirtXen.dsc:122: gEfiMdePkgTokenSpaceGuid.PcdPlatformBootTimeOut|3 EmulatorPkg/EmulatorPkg.dsc:236: gEfiMdePkgTokenSpaceGuid.PcdPlatformBootTimeOut|L"Timeout"|gEfiGlobalVariableGuid|0x0|10 OvmfPkg/OvmfPkgIa32.dsc:541: gEfiMdePkgTokenSpaceGuid.PcdPlatformBootTimeOut|0 OvmfPkg/OvmfPkgIa32X64.dsc:553: gEfiMdePkgTokenSpaceGuid.PcdPlatformBootTimeOut|0 OvmfPkg/OvmfPkgX64.dsc:552: gEfiMdePkgTokenSpaceGuid.PcdPlatformBootTimeOut|0 OvmfPkg/OvmfXen.dsc:470: gEfiMdePkgTokenSpaceGuid.PcdPlatformBootTimeOut|0 UefiPayloadPkg/UefiPayloadPkgIa32.dsc:344: gEfiMdePkgTokenSpaceGuid.PcdPlatformBootTimeOut|3 UefiPayloadPkg/UefiPayloadPkgIa32X64.dsc:345: gEfiMdePkgTokenSpaceGuid.PcdPlatformBootTimeOut|3 OK PcdPlatformBootTimeOut is zero on Ovmf, so how did this ever work? Ahhh gotom.... /Volumes/Case/UDK2018(master)>git blame -L344,344 /Volumes/Case/UDK2018/MdeModulePkg/Universal/BdsDxe/BdsEntry.c 2de1f611be0 (Pete Batard 2019-09-25 23:50:05 +0800 344) PlatformBootManagerWaitCallback (0); This call causes a divide by zero if PcdPlatformBootTimeOut == 0. This fixes my crash: diff --git a/OvmfPkg/Library/PlatformBootManagerLib/BdsPlatform.c b/OvmfPkg/Library/PlatformBootManagerLib/BdsPlatform.c index 70df6b841a..d6ae43e900 100644 --- a/OvmfPkg/Library/PlatformBootManagerLib/BdsPlatform.c +++ b/OvmfPkg/Library/PlatformBootManagerLib/BdsPlatform.c @@ -1634,6 +1634,11 @@ PlatformBootManagerWaitCallback ( UINT16 Timeout; Timeout = PcdGet16 (PcdPlatformBootTimeOut); + if (Timeout == 0) { + Timeout = 100; + } else { + Timeout = (Timeout - TimeoutRemain) * 100 / Timeout; + } Black.Raw = 0x00000000; White.Raw = 0x00FFFFFF; @@ -1643,7 +1648,7 @@ PlatformBootManagerWaitCallback ( Black.Pixel, L"Start boot option", White.Pixel, - (Timeout - TimeoutRemain) * 100 / Timeout, + Timeout, 0 ); } lldb debugger output: (lldb) bt * thread #1, stop reason = signal SIGTRAP * frame #0: 0x0000000007b58a70 CpuDxe.dll:CpuDeadLoop() + 13 at /Volumes/Case/UDK2018/MdePkg/Library/BaseLib/CpuDeadLoop.c:31 frame #1: 0x0000000007b61222 CpuDxe.dll:CommonExceptionHandlerWorker() + 674 at /Volumes/Case/UDK2018/UefiCpuPkg/Library/CpuExceptionHandlerLib/PeiDxeSmmCpuException.c:115 frame #2: 0x0000000007b61624 CpuDxe.dll:CommonExceptionHandler() + 36 at /Volumes/Case/UDK2018/UefiCpuPkg/Library/CpuExceptionHandlerLib/DxeException.c:40 frame #3: 0x0000000007b5ff26 CpuDxe.dll:HasErrorCode() + 230 (lldb) fr sel 1 frame #1: 0x0000000007b61222 CpuDxe.dll:CommonExceptionHandlerWorker() + 674 at /Volumes/Case/UDK2018/UefiCpuPkg/Library/CpuExceptionHandlerLib/PeiDxeSmmCpuException.c:115 91 (ExternalInterruptHandler[ExceptionType]) (ExceptionType, SystemContext); 92 } else if (ExceptionType < CPU_EXCEPTION_NUM) { 93 // 94 // Get Spinlock to display CPU information 95 // 96 while (!AcquireSpinLockOrFail (&ExceptionHandlerData->DisplayMessageSpinLock)) { 97 CpuPause (); 98 } 99 // 100 // Initialize the serial port before dumping. 101 // 102 SerialPortInitialize (); 103 // 104 // Display ExceptionType, CPU information and Image information 105 // 106 DumpImageAndCpuContent (ExceptionType, SystemContext); 107 // 108 // Release Spinlock of output message 109 // 110 ReleaseSpinLock (&ExceptionHandlerData->DisplayMessageSpinLock); 111 // 112 // Enter a dead loop if needn't to execute old IDT handler further 113 // 114 if (ReservedVectors[ExceptionType].Attribute != EFI_VECTOR_HANDOFF_HOOK_BEFORE) { -> 115 CpuDeadLoop (); 116 } 117 } 118 } 119 (lldb) p ExceptionType (EFI_EXCEPTION_TYPE) $0 = 0 (lldb) p SystemContext.SystemContextX64->Rip (UINT64) $1 = 0x0000000007a9cc38 (lldb) p SystemContext.SystemContextX64->Rbp (UINT64) $2 = 0x0000000007e8fc20 (lldb) efi_backtrace --pc 0x0000000007a9cc38 --frame 0x0000000007e8fc20 --symbols frame 0: 0x07a9cc38 BdsDxe:PlatformBootManagerWaitCallback + 35 at /Volumes/Case/UDK2018/OvmfPkg/Library/PlatformBootManagerLib/BdsPlatform.c:1646:37 frame 1: 0x07a9e744 BdsDxe:BdsWait + 269 at /Volumes/Case/UDK2018/MdeModulePkg/Universal/BdsDxe/BdsEntry.c:344:3 frame 2: 0x07a9dff9 BdsDxe:BdsEntry + 2620 at /Volumes/Case/UDK2018/MdeModulePkg/Universal/BdsDxe/BdsEntry.c:1002:5 frame 3: 0x07eb367d DxeCore:DxeMain + 2680 at /Volumes/Case/UDK2018/MdeModulePkg/Core/Dxe/DxeMain/DxeMain.c:544:3 frame 4: 0x07e943cb DxeCore:_ModuleEntryPoint + 20 at /Volumes/Case/UDK2018/MdePkg/Library/DxeCoreEntryPoint/DxeCoreEntryPoint.c:48:3 frame 5: 0x07edc947 DxeIpl.dll`AsmEnableCache frame 6: 0x07ee1e4e DxeIpl:HandOffToDxeCore + 509 at /Volumes/Case/UDK2018/MdeModulePkg/Core/DxeIplPeim/X64/DxeLoadFunc.c:113:3 frame 7: 0x07ee0604 DxeIpl:DxeLoadCore + 1354 at /Volumes/Case/UDK2018/MdeModulePkg/Core/DxeIplPeim/DxeLoad.c:449:3 frame 8: 0x07eeff2f PeiCore.dll`PeiCore.cold.3 + 847 frame 9: 0x07ee9d04 PeiCore:PeiCore + 163 at /Volumes/Case/UDK2018/MdeModulePkg/Core/Pei/PeiMain/PeiMain.c:502:3 frame 10: 0x0082c387 0x0082c387 frame 11: 0x00825dd7 0x00825dd7 frame 12: 0x0082ad27 0x0082ad27 frame 13: 0x0082b3a8 0x0082b3a8 frame 14: 0x0082bf23 0x0082bf23 frame 15: 0x00825e24 0x00825e24 frame 16: 0x00823af2 0x00823af2 frame 17: 0xfffd1db8 SecMain:SecStartupPhase2 + 67 at /Volumes/Case/UDK2018/OvmfPkg/Sec/SecMain.c:858:3 frame 18: 0xfffd1d67 SecMain:SecCoreStartupWithStack + 420 at /Volumes/Case/UDK2018/OvmfPkg/Sec/SecMain.c:821:3 frame 19: 0xfffd1e14 SecMain:ProcessLibraryConstructorList + 0 at /Volumes/Case/UDK2018/Build/OvmfX64/DEBUG_XCODE5/X64/OvmfPkg/Sec/SecMain/DEBUG/AutoGen.c:201 (lldb) l /Volumes/Case/UDK2018/OvmfPkg/Library/PlatformBootManagerLib/BdsPlatform.c:1646 1646 (Timeout - TimeoutRemain) * 100 / Timeout, 1647 0 1648 ); 1649 } 1650 1651 /** 1652 The function is called when no boot option could be launched, 1653 including platform recovery options and options pointing to applications 1654 built into firmware volumes. 1655 (lldb) l /Volumes/Case/UDK2018/MdeModulePkg/Universal/BdsDxe/BdsEntry.c:344 344 PlatformBootManagerWaitCallback (0); 345 DEBUG ((EFI_D_INFO, "[Bds]Exit the waiting!\n")); 346 } 347 348 /** 349 Attempt to boot each boot option in the BootOptions array. 350 351 @param BootOptions Input boot option array. 352 @param BootOptionCount Input boot option count. 353 @param BootManagerMenu Input boot manager menu. 354 Thanks, Andrew Fish [-- Attachment #2: Type: text/html, Size: 49849 bytes --] ^ permalink raw reply related [flat|nested] 10+ messages in thread
* Re: [edk2-devel] OVMF is crashing for me in master 2019-10-10 21:12 OVMF is crashing for me in master Andrew Fish @ 2019-10-11 1:19 ` Liming Gao 2019-10-11 4:59 ` Andrew Fish 2019-10-11 11:50 ` Laszlo Ersek 0 siblings, 2 replies; 10+ messages in thread From: Liming Gao @ 2019-10-11 1:19 UTC (permalink / raw) To: devel@edk2.groups.io, afish@apple.com, Pete Batard [-- Attachment #1: Type: text/plain, Size: 8587 bytes --] Andrew: I verify the change (2de1f611be06ded3a59726a4052a9039be7d459b MdeModulePkg/BdsDxe: Also call PlatformBootManagerWaitCallback on 0) in Emulator. It works, because PCD value is set to 10 in Emulator. Before this change, if TimeOut PCD is zero, BdsEntry doesn't call PlatformBootManagerWaitCallback(). After this change, if TimeOut PCD is zero, BdsEntry still call PlatformBootManagerWaitCallback(). So, it trigs this issue. I agree your fix. Pete: Will you contribute the patch to fix this hang issue in OVMF? Thanks Liming From: devel@edk2.groups.io [mailto:devel@edk2.groups.io] On Behalf Of Andrew Fish via Groups.Io Sent: Friday, October 11, 2019 5:12 AM To: devel@edk2.groups.io; Pete Batard <pete@akeo.ie> Subject: [edk2-devel] OVMF is crashing for me in master This is my flavor of OVMF: build -p OvmfPkg/OvmfPkgX64.dsc -a X64 -t XCODE5 It looks like I took an exception? Is it expected that an unhandled exception just hang in a dead loop? I would have expected some serial output about the failure? Looks like a divide by zero exception. The exception context has PC and FP so I can manually walk the stack. Yikes I see PlatformBootManagerWaitCallback() will fault if PcdPlatformBootTimeOut is zero? /Volumes/Case/UDK2018(master)>git grep PcdPlatformBootTimeOut -- *.dsc ArmVirtPkg/ArmVirtQemu.dsc:194: gEfiMdePkgTokenSpaceGuid.PcdPlatformBootTimeOut|3 ArmVirtPkg/ArmVirtQemuKernel.dsc:191: gEfiMdePkgTokenSpaceGuid.PcdPlatformBootTimeOut|3 ArmVirtPkg/ArmVirtXen.dsc:122: gEfiMdePkgTokenSpaceGuid.PcdPlatformBootTimeOut|3 EmulatorPkg/EmulatorPkg.dsc:236: gEfiMdePkgTokenSpaceGuid.PcdPlatformBootTimeOut|L"Timeout"|gEfiGlobalVariableGuid|0x0|10 OvmfPkg/OvmfPkgIa32.dsc:541: gEfiMdePkgTokenSpaceGuid.PcdPlatformBootTimeOut|0 OvmfPkg/OvmfPkgIa32X64.dsc:553: gEfiMdePkgTokenSpaceGuid.PcdPlatformBootTimeOut|0 OvmfPkg/OvmfPkgX64.dsc:552: gEfiMdePkgTokenSpaceGuid.PcdPlatformBootTimeOut|0 OvmfPkg/OvmfXen.dsc:470: gEfiMdePkgTokenSpaceGuid.PcdPlatformBootTimeOut|0 UefiPayloadPkg/UefiPayloadPkgIa32.dsc:344: gEfiMdePkgTokenSpaceGuid.PcdPlatformBootTimeOut|3 UefiPayloadPkg/UefiPayloadPkgIa32X64.dsc:345: gEfiMdePkgTokenSpaceGuid.PcdPlatformBootTimeOut|3 OK PcdPlatformBootTimeOut is zero on Ovmf, so how did this ever work? Ahhh gotom.... /Volumes/Case/UDK2018(master)>git blame -L344,344 /Volumes/Case/UDK2018/MdeModulePkg/Universal/BdsDxe/BdsEntry.c 2de1f611be0 (Pete Batard 2019-09-25 23:50:05 +0800 344) PlatformBootManagerWaitCallback (0); This call causes a divide by zero if PcdPlatformBootTimeOut == 0. This fixes my crash: diff --git a/OvmfPkg/Library/PlatformBootManagerLib/BdsPlatform.c b/OvmfPkg/Library/PlatformBootManagerLib/BdsPlatform.c index 70df6b841a..d6ae43e900 100644 --- a/OvmfPkg/Library/PlatformBootManagerLib/BdsPlatform.c +++ b/OvmfPkg/Library/PlatformBootManagerLib/BdsPlatform.c @@ -1634,6 +1634,11 @@ PlatformBootManagerWaitCallback ( UINT16 Timeout; Timeout = PcdGet16 (PcdPlatformBootTimeOut); + if (Timeout == 0) { + Timeout = 100; + } else { + Timeout = (Timeout - TimeoutRemain) * 100 / Timeout; + } Black.Raw = 0x00000000; White.Raw = 0x00FFFFFF; @@ -1643,7 +1648,7 @@ PlatformBootManagerWaitCallback ( Black.Pixel, L"Start boot option", White.Pixel, - (Timeout - TimeoutRemain) * 100 / Timeout, + Timeout, 0 ); } lldb debugger output: (lldb) bt * thread #1, stop reason = signal SIGTRAP * frame #0: 0x0000000007b58a70 CpuDxe.dll:CpuDeadLoop() + 13 at /Volumes/Case/UDK2018/MdePkg/Library/BaseLib/CpuDeadLoop.c:31 frame #1: 0x0000000007b61222 CpuDxe.dll:CommonExceptionHandlerWorker() + 674 at /Volumes/Case/UDK2018/UefiCpuPkg/Library/CpuExceptionHandlerLib/PeiDxeSmmCpuException.c:115 frame #2: 0x0000000007b61624 CpuDxe.dll:CommonExceptionHandler() + 36 at /Volumes/Case/UDK2018/UefiCpuPkg/Library/CpuExceptionHandlerLib/DxeException.c:40 frame #3: 0x0000000007b5ff26 CpuDxe.dll:HasErrorCode() + 230 (lldb) fr sel 1 frame #1: 0x0000000007b61222 CpuDxe.dll:CommonExceptionHandlerWorker() + 674 at /Volumes/Case/UDK2018/UefiCpuPkg/Library/CpuExceptionHandlerLib/PeiDxeSmmCpuException.c:115 91 (ExternalInterruptHandler[ExceptionType]) (ExceptionType, SystemContext); 92 } else if (ExceptionType < CPU_EXCEPTION_NUM) { 93 // 94 // Get Spinlock to display CPU information 95 // 96 while (!AcquireSpinLockOrFail (&ExceptionHandlerData->DisplayMessageSpinLock)) { 97 CpuPause (); 98 } 99 // 100 // Initialize the serial port before dumping. 101 // 102 SerialPortInitialize (); 103 // 104 // Display ExceptionType, CPU information and Image information 105 // 106 DumpImageAndCpuContent (ExceptionType, SystemContext); 107 // 108 // Release Spinlock of output message 109 // 110 ReleaseSpinLock (&ExceptionHandlerData->DisplayMessageSpinLock); 111 // 112 // Enter a dead loop if needn't to execute old IDT handler further 113 // 114 if (ReservedVectors[ExceptionType].Attribute != EFI_VECTOR_HANDOFF_HOOK_BEFORE) { -> 115 CpuDeadLoop (); 116 } 117 } 118 } 119 (lldb) p ExceptionType (EFI_EXCEPTION_TYPE) $0 = 0 (lldb) p SystemContext.SystemContextX64->Rip (UINT64) $1 = 0x0000000007a9cc38 (lldb) p SystemContext.SystemContextX64->Rbp (UINT64) $2 = 0x0000000007e8fc20 (lldb) efi_backtrace --pc 0x0000000007a9cc38 --frame 0x0000000007e8fc20 --symbols frame 0: 0x07a9cc38 BdsDxe:PlatformBootManagerWaitCallback + 35 at /Volumes/Case/UDK2018/OvmfPkg/Library/PlatformBootManagerLib/BdsPlatform.c:1646:37 frame 1: 0x07a9e744 BdsDxe:BdsWait + 269 at /Volumes/Case/UDK2018/MdeModulePkg/Universal/BdsDxe/BdsEntry.c:344:3 frame 2: 0x07a9dff9 BdsDxe:BdsEntry + 2620 at /Volumes/Case/UDK2018/MdeModulePkg/Universal/BdsDxe/BdsEntry.c:1002:5 frame 3: 0x07eb367d DxeCore:DxeMain + 2680 at /Volumes/Case/UDK2018/MdeModulePkg/Core/Dxe/DxeMain/DxeMain.c:544:3 frame 4: 0x07e943cb DxeCore:_ModuleEntryPoint + 20 at /Volumes/Case/UDK2018/MdePkg/Library/DxeCoreEntryPoint/DxeCoreEntryPoint.c:48:3 frame 5: 0x07edc947 DxeIpl.dll`AsmEnableCache frame 6: 0x07ee1e4e DxeIpl:HandOffToDxeCore + 509 at /Volumes/Case/UDK2018/MdeModulePkg/Core/DxeIplPeim/X64/DxeLoadFunc.c:113:3 frame 7: 0x07ee0604 DxeIpl:DxeLoadCore + 1354 at /Volumes/Case/UDK2018/MdeModulePkg/Core/DxeIplPeim/DxeLoad.c:449:3 frame 8: 0x07eeff2f PeiCore.dll`PeiCore.cold.3 + 847 frame 9: 0x07ee9d04 PeiCore:PeiCore + 163 at /Volumes/Case/UDK2018/MdeModulePkg/Core/Pei/PeiMain/PeiMain.c:502:3 frame 10: 0x0082c387 0x0082c387 frame 11: 0x00825dd7 0x00825dd7 frame 12: 0x0082ad27 0x0082ad27 frame 13: 0x0082b3a8 0x0082b3a8 frame 14: 0x0082bf23 0x0082bf23 frame 15: 0x00825e24 0x00825e24 frame 16: 0x00823af2 0x00823af2 frame 17: 0xfffd1db8 SecMain:SecStartupPhase2 + 67 at /Volumes/Case/UDK2018/OvmfPkg/Sec/SecMain.c:858:3 frame 18: 0xfffd1d67 SecMain:SecCoreStartupWithStack + 420 at /Volumes/Case/UDK2018/OvmfPkg/Sec/SecMain.c:821:3 frame 19: 0xfffd1e14 SecMain:ProcessLibraryConstructorList + 0 at /Volumes/Case/UDK2018/Build/OvmfX64/DEBUG_XCODE5/X64/OvmfPkg/Sec/SecMain/DEBUG/AutoGen.c:201 (lldb) l /Volumes/Case/UDK2018/OvmfPkg/Library/PlatformBootManagerLib/BdsPlatform.c:1646 1646 (Timeout - TimeoutRemain) * 100 / Timeout, 1647 0 1648 ); 1649 } 1650 1651 /** 1652 The function is called when no boot option could be launched, 1653 including platform recovery options and options pointing to applications 1654 built into firmware volumes. 1655 (lldb) l /Volumes/Case/UDK2018/MdeModulePkg/Universal/BdsDxe/BdsEntry.c:344 344 PlatformBootManagerWaitCallback (0); 345 DEBUG ((EFI_D_INFO, "[Bds]Exit the waiting!\n")); 346 } 347 348 /** 349 Attempt to boot each boot option in the BootOptions array. 350 351 @param BootOptions Input boot option array. 352 @param BootOptionCount Input boot option count. 353 @param BootManagerMenu Input boot manager menu. 354 Thanks, Andrew Fish [-- Attachment #2: Type: text/html, Size: 46769 bytes --] ^ permalink raw reply related [flat|nested] 10+ messages in thread
* Re: [edk2-devel] OVMF is crashing for me in master 2019-10-11 1:19 ` [edk2-devel] " Liming Gao @ 2019-10-11 4:59 ` Andrew Fish 2019-10-11 11:53 ` Laszlo Ersek 2019-10-11 11:50 ` Laszlo Ersek 1 sibling, 1 reply; 10+ messages in thread From: Andrew Fish @ 2019-10-11 4:59 UTC (permalink / raw) To: Gao, Liming; +Cc: devel@edk2.groups.io, Pete Batard [-- Attachment #1: Type: text/plain, Size: 9202 bytes --] Liming, Thanks for looking into this! Can someone also answer my question about the expected behavior of taking an exception in OVMF? Is the CpuDeadloop() expected? Thanks, Andrew Fish > On Oct 10, 2019, at 6:19 PM, Gao, Liming <liming.gao@intel.com> wrote: > > Andrew: > I verify the change (2de1f611be06ded3a59726a4052a9039be7d459b MdeModulePkg/BdsDxe: Also call PlatformBootManagerWaitCallback on 0) in Emulator. > It works, because PCD value is set to 10 in Emulator. > > Before this change, if TimeOut PCD is zero, BdsEntry doesn’t call PlatformBootManagerWaitCallback(). > After this change, if TimeOut PCD is zero, BdsEntry still call PlatformBootManagerWaitCallback(). So, it trigs this issue. I agree your fix. > > Pete: > Will you contribute the patch to fix this hang issue in OVMF? > > Thanks > Liming > From: devel@edk2.groups.io [mailto:devel@edk2.groups.io] On Behalf Of Andrew Fish via Groups.Io > Sent: Friday, October 11, 2019 5:12 AM > To: devel@edk2.groups.io; Pete Batard <pete@akeo.ie> > Subject: [edk2-devel] OVMF is crashing for me in master > > This is my flavor of OVMF: build -p OvmfPkg/OvmfPkgX64.dsc -a X64 -t XCODE5 > > It looks like I took an exception? Is it expected that an unhandled exception just hang in a dead loop? I would have expected some serial output about the failure? > > Looks like a divide by zero exception. The exception context has PC and FP so I can manually walk the stack. Yikes I see PlatformBootManagerWaitCallback() will fault if PcdPlatformBootTimeOut is zero? > /Volumes/Case/UDK2018(master)>git grep PcdPlatformBootTimeOut -- *.dsc > ArmVirtPkg/ArmVirtQemu.dsc:194: gEfiMdePkgTokenSpaceGuid.PcdPlatformBootTimeOut|3 > ArmVirtPkg/ArmVirtQemuKernel.dsc:191: gEfiMdePkgTokenSpaceGuid.PcdPlatformBootTimeOut|3 > ArmVirtPkg/ArmVirtXen.dsc:122: gEfiMdePkgTokenSpaceGuid.PcdPlatformBootTimeOut|3 > EmulatorPkg/EmulatorPkg.dsc:236: gEfiMdePkgTokenSpaceGuid.PcdPlatformBootTimeOut|L"Timeout"|gEfiGlobalVariableGuid|0x0|10 > OvmfPkg/OvmfPkgIa32.dsc:541: gEfiMdePkgTokenSpaceGuid.PcdPlatformBootTimeOut|0 > OvmfPkg/OvmfPkgIa32X64.dsc:553: gEfiMdePkgTokenSpaceGuid.PcdPlatformBootTimeOut|0 > OvmfPkg/OvmfPkgX64.dsc:552: gEfiMdePkgTokenSpaceGuid.PcdPlatformBootTimeOut|0 > OvmfPkg/OvmfXen.dsc:470: gEfiMdePkgTokenSpaceGuid.PcdPlatformBootTimeOut|0 > UefiPayloadPkg/UefiPayloadPkgIa32.dsc:344: gEfiMdePkgTokenSpaceGuid.PcdPlatformBootTimeOut|3 > UefiPayloadPkg/UefiPayloadPkgIa32X64.dsc:345: gEfiMdePkgTokenSpaceGuid.PcdPlatformBootTimeOut|3 > > > OK PcdPlatformBootTimeOut is zero on Ovmf, so how did this ever work? > > > Ahhh gotom.... > /Volumes/Case/UDK2018(master)>git blame -L344,344 /Volumes/Case/UDK2018/MdeModulePkg/Universal/BdsDxe/BdsEntry.c > 2de1f611be0 (Pete Batard 2019-09-25 23:50:05 +0800 344) PlatformBootManagerWaitCallback (0); > > > This call causes a divide by zero if PcdPlatformBootTimeOut == 0. > > This fixes my crash: > diff --git a/OvmfPkg/Library/PlatformBootManagerLib/BdsPlatform.c b/OvmfPkg/Library/PlatformBootManagerLib/BdsPlatform.c > index 70df6b841a..d6ae43e900 100644 > --- a/OvmfPkg/Library/PlatformBootManagerLib/BdsPlatform.c > +++ b/OvmfPkg/Library/PlatformBootManagerLib/BdsPlatform.c > @@ -1634,6 +1634,11 @@ PlatformBootManagerWaitCallback ( > UINT16 Timeout; > > Timeout = PcdGet16 (PcdPlatformBootTimeOut); > + if (Timeout == 0) { > + Timeout = 100; > + } else { > + Timeout = (Timeout - TimeoutRemain) * 100 / Timeout; > + } > > Black.Raw = 0x00000000; > White.Raw = 0x00FFFFFF; > @@ -1643,7 +1648,7 @@ PlatformBootManagerWaitCallback ( > Black.Pixel, > L"Start boot option", > White.Pixel, > - (Timeout - TimeoutRemain) * 100 / Timeout, > + Timeout, > 0 > ); > } > > > > lldb debugger output: > > (lldb) bt > * thread #1, stop reason = signal SIGTRAP > * frame #0: 0x0000000007b58a70 CpuDxe.dll:CpuDeadLoop() + 13 at /Volumes/Case/UDK2018/MdePkg/Library/BaseLib/CpuDeadLoop.c:31 > frame #1: 0x0000000007b61222 CpuDxe.dll:CommonExceptionHandlerWorker() + 674 at /Volumes/Case/UDK2018/UefiCpuPkg/Library/CpuExceptionHandlerLib/PeiDxeSmmCpuException.c:115 > frame #2: 0x0000000007b61624 CpuDxe.dll:CommonExceptionHandler() + 36 at /Volumes/Case/UDK2018/UefiCpuPkg/Library/CpuExceptionHandlerLib/DxeException.c:40 > frame #3: 0x0000000007b5ff26 CpuDxe.dll:HasErrorCode() + 230 > (lldb) fr sel 1 > frame #1: 0x0000000007b61222 CpuDxe.dll:CommonExceptionHandlerWorker() + 674 at /Volumes/Case/UDK2018/UefiCpuPkg/Library/CpuExceptionHandlerLib/PeiDxeSmmCpuException.c:115 > 91 (ExternalInterruptHandler[ExceptionType]) (ExceptionType, SystemContext); > 92 } else if (ExceptionType < CPU_EXCEPTION_NUM) { > 93 // > 94 // Get Spinlock to display CPU information > 95 // > 96 while (!AcquireSpinLockOrFail (&ExceptionHandlerData->DisplayMessageSpinLock)) { > 97 CpuPause (); > 98 } > 99 // > 100 // Initialize the serial port before dumping. > 101 // > 102 SerialPortInitialize (); > 103 // > 104 // Display ExceptionType, CPU information and Image information > 105 // > 106 DumpImageAndCpuContent (ExceptionType, SystemContext); > 107 // > 108 // Release Spinlock of output message > 109 // > 110 ReleaseSpinLock (&ExceptionHandlerData->DisplayMessageSpinLock); > 111 // > 112 // Enter a dead loop if needn't to execute old IDT handler further > 113 // > 114 if (ReservedVectors[ExceptionType].Attribute != EFI_VECTOR_HANDOFF_HOOK_BEFORE) { > -> 115 CpuDeadLoop (); > 116 } > 117 } > 118 } > 119 > (lldb) p ExceptionType > (EFI_EXCEPTION_TYPE) $0 = 0 > (lldb) p SystemContext.SystemContextX64->Rip > (UINT64) $1 = 0x0000000007a9cc38 > (lldb) p SystemContext.SystemContextX64->Rbp > (UINT64) $2 = 0x0000000007e8fc20 > (lldb) efi_backtrace --pc 0x0000000007a9cc38 --frame 0x0000000007e8fc20 --symbols > frame 0: 0x07a9cc38 BdsDxe:PlatformBootManagerWaitCallback + 35 at /Volumes/Case/UDK2018/OvmfPkg/Library/PlatformBootManagerLib/BdsPlatform.c:1646:37 > frame 1: 0x07a9e744 BdsDxe:BdsWait + 269 at /Volumes/Case/UDK2018/MdeModulePkg/Universal/BdsDxe/BdsEntry.c:344:3 > frame 2: 0x07a9dff9 BdsDxe:BdsEntry + 2620 at /Volumes/Case/UDK2018/MdeModulePkg/Universal/BdsDxe/BdsEntry.c:1002:5 > frame 3: 0x07eb367d DxeCore:DxeMain + 2680 at /Volumes/Case/UDK2018/MdeModulePkg/Core/Dxe/DxeMain/DxeMain.c:544:3 > frame 4: 0x07e943cb DxeCore:_ModuleEntryPoint + 20 at /Volumes/Case/UDK2018/MdePkg/Library/DxeCoreEntryPoint/DxeCoreEntryPoint.c:48:3 > frame 5: 0x07edc947 DxeIpl.dll`AsmEnableCache > frame 6: 0x07ee1e4e DxeIpl:HandOffToDxeCore + 509 at /Volumes/Case/UDK2018/MdeModulePkg/Core/DxeIplPeim/X64/DxeLoadFunc.c:113:3 > frame 7: 0x07ee0604 DxeIpl:DxeLoadCore + 1354 at /Volumes/Case/UDK2018/MdeModulePkg/Core/DxeIplPeim/DxeLoad.c:449:3 > frame 8: 0x07eeff2f PeiCore.dll`PeiCore.cold.3 + 847 > frame 9: 0x07ee9d04 PeiCore:PeiCore + 163 at /Volumes/Case/UDK2018/MdeModulePkg/Core/Pei/PeiMain/PeiMain.c:502:3 > frame 10: 0x0082c387 0x0082c387 > frame 11: 0x00825dd7 0x00825dd7 > frame 12: 0x0082ad27 0x0082ad27 > frame 13: 0x0082b3a8 0x0082b3a8 > frame 14: 0x0082bf23 0x0082bf23 > frame 15: 0x00825e24 0x00825e24 > frame 16: 0x00823af2 0x00823af2 > frame 17: 0xfffd1db8 SecMain:SecStartupPhase2 + 67 at /Volumes/Case/UDK2018/OvmfPkg/Sec/SecMain.c:858:3 > frame 18: 0xfffd1d67 SecMain:SecCoreStartupWithStack + 420 at /Volumes/Case/UDK2018/OvmfPkg/Sec/SecMain.c:821:3 > frame 19: 0xfffd1e14 SecMain:ProcessLibraryConstructorList + 0 at /Volumes/Case/UDK2018/Build/OvmfX64/DEBUG_XCODE5/X64/OvmfPkg/Sec/SecMain/DEBUG/AutoGen.c:201 > > (lldb) l /Volumes/Case/UDK2018/OvmfPkg/Library/PlatformBootManagerLib/BdsPlatform.c:1646 > 1646 (Timeout - TimeoutRemain) * 100 / Timeout, > 1647 0 > 1648 ); > 1649 } > 1650 > 1651 /** > 1652 The function is called when no boot option could be launched, > 1653 including platform recovery options and options pointing to applications > 1654 built into firmware volumes. > 1655 > (lldb) l /Volumes/Case/UDK2018/MdeModulePkg/Universal/BdsDxe/BdsEntry.c:344 > 344 PlatformBootManagerWaitCallback (0); > 345 DEBUG ((EFI_D_INFO, "[Bds]Exit the waiting!\n")); > 346 } > 347 > 348 /** > 349 Attempt to boot each boot option in the BootOptions array. > 350 > 351 @param BootOptions Input boot option array. > 352 @param BootOptionCount Input boot option count. > 353 @param BootManagerMenu Input boot manager menu. > 354 > > > Thanks, > > Andrew Fish > > [-- Attachment #2: Type: text/html, Size: 68953 bytes --] ^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [edk2-devel] OVMF is crashing for me in master 2019-10-11 4:59 ` Andrew Fish @ 2019-10-11 11:53 ` Laszlo Ersek 2019-10-11 12:49 ` Andrew Fish 0 siblings, 1 reply; 10+ messages in thread From: Laszlo Ersek @ 2019-10-11 11:53 UTC (permalink / raw) To: devel, afish, Gao, Liming; +Cc: Pete Batard On 10/11/19 06:59, Andrew Fish via Groups.Io wrote: > Liming, > > Thanks for looking into this! > > Can someone also answer my question about the expected behavior of taking an exception in OVMF? Is the CpuDeadloop() expected? Yes, it is. The exception handler dumps the register file and the stack to the emulated serial port, not to the QEMU debug port. When looking for OVMF debug messages, people usually (and rightly) check wherever the QEMU debug port has been redirected. (Unless they built OVMF with -D DEBUG_ON_SERIAL_PORT.) However, the exception handler always dumps the state to the serial port, regardless of DEBUG_ON_SERIAL_PORT. This can be confusing, as the normally consulted debug log has no indication of the issue. Thanks Laszlo > > Thanks, > > Andrew Fish > >> On Oct 10, 2019, at 6:19 PM, Gao, Liming <liming.gao@intel.com> wrote: >> >> Andrew: >> I verify the change (2de1f611be06ded3a59726a4052a9039be7d459b MdeModulePkg/BdsDxe: Also call PlatformBootManagerWaitCallback on 0) in Emulator. >> It works, because PCD value is set to 10 in Emulator. >> >> Before this change, if TimeOut PCD is zero, BdsEntry doesn’t call PlatformBootManagerWaitCallback(). >> After this change, if TimeOut PCD is zero, BdsEntry still call PlatformBootManagerWaitCallback(). So, it trigs this issue. I agree your fix. >> >> Pete: >> Will you contribute the patch to fix this hang issue in OVMF? >> >> Thanks >> Liming >> From: devel@edk2.groups.io [mailto:devel@edk2.groups.io] On Behalf Of Andrew Fish via Groups.Io >> Sent: Friday, October 11, 2019 5:12 AM >> To: devel@edk2.groups.io; Pete Batard <pete@akeo.ie> >> Subject: [edk2-devel] OVMF is crashing for me in master >> >> This is my flavor of OVMF: build -p OvmfPkg/OvmfPkgX64.dsc -a X64 -t XCODE5 >> >> It looks like I took an exception? Is it expected that an unhandled exception just hang in a dead loop? I would have expected some serial output about the failure? >> >> Looks like a divide by zero exception. The exception context has PC and FP so I can manually walk the stack. Yikes I see PlatformBootManagerWaitCallback() will fault if PcdPlatformBootTimeOut is zero? >> /Volumes/Case/UDK2018(master)>git grep PcdPlatformBootTimeOut -- *.dsc >> ArmVirtPkg/ArmVirtQemu.dsc:194: gEfiMdePkgTokenSpaceGuid.PcdPlatformBootTimeOut|3 >> ArmVirtPkg/ArmVirtQemuKernel.dsc:191: gEfiMdePkgTokenSpaceGuid.PcdPlatformBootTimeOut|3 >> ArmVirtPkg/ArmVirtXen.dsc:122: gEfiMdePkgTokenSpaceGuid.PcdPlatformBootTimeOut|3 >> EmulatorPkg/EmulatorPkg.dsc:236: gEfiMdePkgTokenSpaceGuid.PcdPlatformBootTimeOut|L"Timeout"|gEfiGlobalVariableGuid|0x0|10 >> OvmfPkg/OvmfPkgIa32.dsc:541: gEfiMdePkgTokenSpaceGuid.PcdPlatformBootTimeOut|0 >> OvmfPkg/OvmfPkgIa32X64.dsc:553: gEfiMdePkgTokenSpaceGuid.PcdPlatformBootTimeOut|0 >> OvmfPkg/OvmfPkgX64.dsc:552: gEfiMdePkgTokenSpaceGuid.PcdPlatformBootTimeOut|0 >> OvmfPkg/OvmfXen.dsc:470: gEfiMdePkgTokenSpaceGuid.PcdPlatformBootTimeOut|0 >> UefiPayloadPkg/UefiPayloadPkgIa32.dsc:344: gEfiMdePkgTokenSpaceGuid.PcdPlatformBootTimeOut|3 >> UefiPayloadPkg/UefiPayloadPkgIa32X64.dsc:345: gEfiMdePkgTokenSpaceGuid.PcdPlatformBootTimeOut|3 >> >> >> OK PcdPlatformBootTimeOut is zero on Ovmf, so how did this ever work? >> >> >> Ahhh gotom.... >> /Volumes/Case/UDK2018(master)>git blame -L344,344 /Volumes/Case/UDK2018/MdeModulePkg/Universal/BdsDxe/BdsEntry.c >> 2de1f611be0 (Pete Batard 2019-09-25 23:50:05 +0800 344) PlatformBootManagerWaitCallback (0); >> >> >> This call causes a divide by zero if PcdPlatformBootTimeOut == 0. >> >> This fixes my crash: >> diff --git a/OvmfPkg/Library/PlatformBootManagerLib/BdsPlatform.c b/OvmfPkg/Library/PlatformBootManagerLib/BdsPlatform.c >> index 70df6b841a..d6ae43e900 100644 >> --- a/OvmfPkg/Library/PlatformBootManagerLib/BdsPlatform.c >> +++ b/OvmfPkg/Library/PlatformBootManagerLib/BdsPlatform.c >> @@ -1634,6 +1634,11 @@ PlatformBootManagerWaitCallback ( >> UINT16 Timeout; >> >> Timeout = PcdGet16 (PcdPlatformBootTimeOut); >> + if (Timeout == 0) { >> + Timeout = 100; >> + } else { >> + Timeout = (Timeout - TimeoutRemain) * 100 / Timeout; >> + } >> >> Black.Raw = 0x00000000; >> White.Raw = 0x00FFFFFF; >> @@ -1643,7 +1648,7 @@ PlatformBootManagerWaitCallback ( >> Black.Pixel, >> L"Start boot option", >> White.Pixel, >> - (Timeout - TimeoutRemain) * 100 / Timeout, >> + Timeout, >> 0 >> ); >> } >> >> >> >> lldb debugger output: >> >> (lldb) bt >> * thread #1, stop reason = signal SIGTRAP >> * frame #0: 0x0000000007b58a70 CpuDxe.dll:CpuDeadLoop() + 13 at /Volumes/Case/UDK2018/MdePkg/Library/BaseLib/CpuDeadLoop.c:31 >> frame #1: 0x0000000007b61222 CpuDxe.dll:CommonExceptionHandlerWorker() + 674 at /Volumes/Case/UDK2018/UefiCpuPkg/Library/CpuExceptionHandlerLib/PeiDxeSmmCpuException.c:115 >> frame #2: 0x0000000007b61624 CpuDxe.dll:CommonExceptionHandler() + 36 at /Volumes/Case/UDK2018/UefiCpuPkg/Library/CpuExceptionHandlerLib/DxeException.c:40 >> frame #3: 0x0000000007b5ff26 CpuDxe.dll:HasErrorCode() + 230 >> (lldb) fr sel 1 >> frame #1: 0x0000000007b61222 CpuDxe.dll:CommonExceptionHandlerWorker() + 674 at /Volumes/Case/UDK2018/UefiCpuPkg/Library/CpuExceptionHandlerLib/PeiDxeSmmCpuException.c:115 >> 91 (ExternalInterruptHandler[ExceptionType]) (ExceptionType, SystemContext); >> 92 } else if (ExceptionType < CPU_EXCEPTION_NUM) { >> 93 // >> 94 // Get Spinlock to display CPU information >> 95 // >> 96 while (!AcquireSpinLockOrFail (&ExceptionHandlerData->DisplayMessageSpinLock)) { >> 97 CpuPause (); >> 98 } >> 99 // >> 100 // Initialize the serial port before dumping. >> 101 // >> 102 SerialPortInitialize (); >> 103 // >> 104 // Display ExceptionType, CPU information and Image information >> 105 // >> 106 DumpImageAndCpuContent (ExceptionType, SystemContext); >> 107 // >> 108 // Release Spinlock of output message >> 109 // >> 110 ReleaseSpinLock (&ExceptionHandlerData->DisplayMessageSpinLock); >> 111 // >> 112 // Enter a dead loop if needn't to execute old IDT handler further >> 113 // >> 114 if (ReservedVectors[ExceptionType].Attribute != EFI_VECTOR_HANDOFF_HOOK_BEFORE) { >> -> 115 CpuDeadLoop (); >> 116 } >> 117 } >> 118 } >> 119 >> (lldb) p ExceptionType >> (EFI_EXCEPTION_TYPE) $0 = 0 >> (lldb) p SystemContext.SystemContextX64->Rip >> (UINT64) $1 = 0x0000000007a9cc38 >> (lldb) p SystemContext.SystemContextX64->Rbp >> (UINT64) $2 = 0x0000000007e8fc20 >> (lldb) efi_backtrace --pc 0x0000000007a9cc38 --frame 0x0000000007e8fc20 --symbols >> frame 0: 0x07a9cc38 BdsDxe:PlatformBootManagerWaitCallback + 35 at /Volumes/Case/UDK2018/OvmfPkg/Library/PlatformBootManagerLib/BdsPlatform.c:1646:37 >> frame 1: 0x07a9e744 BdsDxe:BdsWait + 269 at /Volumes/Case/UDK2018/MdeModulePkg/Universal/BdsDxe/BdsEntry.c:344:3 >> frame 2: 0x07a9dff9 BdsDxe:BdsEntry + 2620 at /Volumes/Case/UDK2018/MdeModulePkg/Universal/BdsDxe/BdsEntry.c:1002:5 >> frame 3: 0x07eb367d DxeCore:DxeMain + 2680 at /Volumes/Case/UDK2018/MdeModulePkg/Core/Dxe/DxeMain/DxeMain.c:544:3 >> frame 4: 0x07e943cb DxeCore:_ModuleEntryPoint + 20 at /Volumes/Case/UDK2018/MdePkg/Library/DxeCoreEntryPoint/DxeCoreEntryPoint.c:48:3 >> frame 5: 0x07edc947 DxeIpl.dll`AsmEnableCache >> frame 6: 0x07ee1e4e DxeIpl:HandOffToDxeCore + 509 at /Volumes/Case/UDK2018/MdeModulePkg/Core/DxeIplPeim/X64/DxeLoadFunc.c:113:3 >> frame 7: 0x07ee0604 DxeIpl:DxeLoadCore + 1354 at /Volumes/Case/UDK2018/MdeModulePkg/Core/DxeIplPeim/DxeLoad.c:449:3 >> frame 8: 0x07eeff2f PeiCore.dll`PeiCore.cold.3 + 847 >> frame 9: 0x07ee9d04 PeiCore:PeiCore + 163 at /Volumes/Case/UDK2018/MdeModulePkg/Core/Pei/PeiMain/PeiMain.c:502:3 >> frame 10: 0x0082c387 0x0082c387 >> frame 11: 0x00825dd7 0x00825dd7 >> frame 12: 0x0082ad27 0x0082ad27 >> frame 13: 0x0082b3a8 0x0082b3a8 >> frame 14: 0x0082bf23 0x0082bf23 >> frame 15: 0x00825e24 0x00825e24 >> frame 16: 0x00823af2 0x00823af2 >> frame 17: 0xfffd1db8 SecMain:SecStartupPhase2 + 67 at /Volumes/Case/UDK2018/OvmfPkg/Sec/SecMain.c:858:3 >> frame 18: 0xfffd1d67 SecMain:SecCoreStartupWithStack + 420 at /Volumes/Case/UDK2018/OvmfPkg/Sec/SecMain.c:821:3 >> frame 19: 0xfffd1e14 SecMain:ProcessLibraryConstructorList + 0 at /Volumes/Case/UDK2018/Build/OvmfX64/DEBUG_XCODE5/X64/OvmfPkg/Sec/SecMain/DEBUG/AutoGen.c:201 >> >> (lldb) l /Volumes/Case/UDK2018/OvmfPkg/Library/PlatformBootManagerLib/BdsPlatform.c:1646 >> 1646 (Timeout - TimeoutRemain) * 100 / Timeout, >> 1647 0 >> 1648 ); >> 1649 } >> 1650 >> 1651 /** >> 1652 The function is called when no boot option could be launched, >> 1653 including platform recovery options and options pointing to applications >> 1654 built into firmware volumes. >> 1655 >> (lldb) l /Volumes/Case/UDK2018/MdeModulePkg/Universal/BdsDxe/BdsEntry.c:344 >> 344 PlatformBootManagerWaitCallback (0); >> 345 DEBUG ((EFI_D_INFO, "[Bds]Exit the waiting!\n")); >> 346 } >> 347 >> 348 /** >> 349 Attempt to boot each boot option in the BootOptions array. >> 350 >> 351 @param BootOptions Input boot option array. >> 352 @param BootOptionCount Input boot option count. >> 353 @param BootManagerMenu Input boot manager menu. >> 354 >> >> >> Thanks, >> >> Andrew Fish >> >> > > > > > ^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [edk2-devel] OVMF is crashing for me in master 2019-10-11 11:53 ` Laszlo Ersek @ 2019-10-11 12:49 ` Andrew Fish 0 siblings, 0 replies; 10+ messages in thread From: Andrew Fish @ 2019-10-11 12:49 UTC (permalink / raw) To: Laszlo Ersek; +Cc: devel, Gao, Liming, Pete Batard [-- Attachment #1: Type: text/plain, Size: 10374 bytes --] > On Oct 11, 2019, at 4:53 AM, Laszlo Ersek <lersek@redhat.com> wrote: > > On 10/11/19 06:59, Andrew Fish via Groups.Io wrote: >> Liming, >> >> Thanks for looking into this! >> >> Can someone also answer my question about the expected behavior of taking an exception in OVMF? Is the CpuDeadloop() expected? > > Yes, it is. > > The exception handler dumps the register file and the stack to the > emulated serial port, not to the QEMU debug port. > > When looking for OVMF debug messages, people usually (and rightly) check > wherever the QEMU debug port has been redirected. (Unless they built > OVMF with -D DEBUG_ON_SERIAL_PORT.) However, the exception handler > always dumps the state to the serial port, regardless of > DEBUG_ON_SERIAL_PORT. This can be confusing, as the normally consulted > debug log has no indication of the issue. > Laszlo, Thanks if I add -serial file:serial.log to the QEMU command line I see the exception in serial.log. Thanks, Andrew Fish > Thanks > Laszlo > >> >> Thanks, >> >> Andrew Fish >> >>> On Oct 10, 2019, at 6:19 PM, Gao, Liming <liming.gao@intel.com> wrote: >>> >>> Andrew: >>> I verify the change (2de1f611be06ded3a59726a4052a9039be7d459b MdeModulePkg/BdsDxe: Also call PlatformBootManagerWaitCallback on 0) in Emulator. >>> It works, because PCD value is set to 10 in Emulator. >>> >>> Before this change, if TimeOut PCD is zero, BdsEntry doesn’t call PlatformBootManagerWaitCallback(). >>> After this change, if TimeOut PCD is zero, BdsEntry still call PlatformBootManagerWaitCallback(). So, it trigs this issue. I agree your fix. >>> >>> Pete: >>> Will you contribute the patch to fix this hang issue in OVMF? >>> >>> Thanks >>> Liming >>> From: devel@edk2.groups.io [mailto:devel@edk2.groups.io] On Behalf Of Andrew Fish via Groups.Io >>> Sent: Friday, October 11, 2019 5:12 AM >>> To: devel@edk2.groups.io; Pete Batard <pete@akeo.ie> >>> Subject: [edk2-devel] OVMF is crashing for me in master >>> >>> This is my flavor of OVMF: build -p OvmfPkg/OvmfPkgX64.dsc -a X64 -t XCODE5 >>> >>> It looks like I took an exception? Is it expected that an unhandled exception just hang in a dead loop? I would have expected some serial output about the failure? >>> >>> Looks like a divide by zero exception. The exception context has PC and FP so I can manually walk the stack. Yikes I see PlatformBootManagerWaitCallback() will fault if PcdPlatformBootTimeOut is zero? >>> /Volumes/Case/UDK2018(master)>git grep PcdPlatformBootTimeOut -- *.dsc >>> ArmVirtPkg/ArmVirtQemu.dsc:194: gEfiMdePkgTokenSpaceGuid.PcdPlatformBootTimeOut|3 >>> ArmVirtPkg/ArmVirtQemuKernel.dsc:191: gEfiMdePkgTokenSpaceGuid.PcdPlatformBootTimeOut|3 >>> ArmVirtPkg/ArmVirtXen.dsc:122: gEfiMdePkgTokenSpaceGuid.PcdPlatformBootTimeOut|3 >>> EmulatorPkg/EmulatorPkg.dsc:236: gEfiMdePkgTokenSpaceGuid.PcdPlatformBootTimeOut|L"Timeout"|gEfiGlobalVariableGuid|0x0|10 >>> OvmfPkg/OvmfPkgIa32.dsc:541: gEfiMdePkgTokenSpaceGuid.PcdPlatformBootTimeOut|0 >>> OvmfPkg/OvmfPkgIa32X64.dsc:553: gEfiMdePkgTokenSpaceGuid.PcdPlatformBootTimeOut|0 >>> OvmfPkg/OvmfPkgX64.dsc:552: gEfiMdePkgTokenSpaceGuid.PcdPlatformBootTimeOut|0 >>> OvmfPkg/OvmfXen.dsc:470: gEfiMdePkgTokenSpaceGuid.PcdPlatformBootTimeOut|0 >>> UefiPayloadPkg/UefiPayloadPkgIa32.dsc:344: gEfiMdePkgTokenSpaceGuid.PcdPlatformBootTimeOut|3 >>> UefiPayloadPkg/UefiPayloadPkgIa32X64.dsc:345: gEfiMdePkgTokenSpaceGuid.PcdPlatformBootTimeOut|3 >>> >>> >>> OK PcdPlatformBootTimeOut is zero on Ovmf, so how did this ever work? >>> >>> >>> Ahhh gotom.... >>> /Volumes/Case/UDK2018(master)>git blame -L344,344 /Volumes/Case/UDK2018/MdeModulePkg/Universal/BdsDxe/BdsEntry.c >>> 2de1f611be0 (Pete Batard 2019-09-25 23:50:05 +0800 344) PlatformBootManagerWaitCallback (0); >>> >>> >>> This call causes a divide by zero if PcdPlatformBootTimeOut == 0. >>> >>> This fixes my crash: >>> diff --git a/OvmfPkg/Library/PlatformBootManagerLib/BdsPlatform.c b/OvmfPkg/Library/PlatformBootManagerLib/BdsPlatform.c >>> index 70df6b841a..d6ae43e900 100644 >>> --- a/OvmfPkg/Library/PlatformBootManagerLib/BdsPlatform.c >>> +++ b/OvmfPkg/Library/PlatformBootManagerLib/BdsPlatform.c >>> @@ -1634,6 +1634,11 @@ PlatformBootManagerWaitCallback ( >>> UINT16 Timeout; >>> >>> Timeout = PcdGet16 (PcdPlatformBootTimeOut); >>> + if (Timeout == 0) { >>> + Timeout = 100; >>> + } else { >>> + Timeout = (Timeout - TimeoutRemain) * 100 / Timeout; >>> + } >>> >>> Black.Raw = 0x00000000; >>> White.Raw = 0x00FFFFFF; >>> @@ -1643,7 +1648,7 @@ PlatformBootManagerWaitCallback ( >>> Black.Pixel, >>> L"Start boot option", >>> White.Pixel, >>> - (Timeout - TimeoutRemain) * 100 / Timeout, >>> + Timeout, >>> 0 >>> ); >>> } >>> >>> >>> >>> lldb debugger output: >>> >>> (lldb) bt >>> * thread #1, stop reason = signal SIGTRAP >>> * frame #0: 0x0000000007b58a70 CpuDxe.dll:CpuDeadLoop() + 13 at /Volumes/Case/UDK2018/MdePkg/Library/BaseLib/CpuDeadLoop.c:31 >>> frame #1: 0x0000000007b61222 CpuDxe.dll:CommonExceptionHandlerWorker() + 674 at /Volumes/Case/UDK2018/UefiCpuPkg/Library/CpuExceptionHandlerLib/PeiDxeSmmCpuException.c:115 >>> frame #2: 0x0000000007b61624 CpuDxe.dll:CommonExceptionHandler() + 36 at /Volumes/Case/UDK2018/UefiCpuPkg/Library/CpuExceptionHandlerLib/DxeException.c:40 >>> frame #3: 0x0000000007b5ff26 CpuDxe.dll:HasErrorCode() + 230 >>> (lldb) fr sel 1 >>> frame #1: 0x0000000007b61222 CpuDxe.dll:CommonExceptionHandlerWorker() + 674 at /Volumes/Case/UDK2018/UefiCpuPkg/Library/CpuExceptionHandlerLib/PeiDxeSmmCpuException.c:115 >>> 91 (ExternalInterruptHandler[ExceptionType]) (ExceptionType, SystemContext); >>> 92 } else if (ExceptionType < CPU_EXCEPTION_NUM) { >>> 93 // >>> 94 // Get Spinlock to display CPU information >>> 95 // >>> 96 while (!AcquireSpinLockOrFail (&ExceptionHandlerData->DisplayMessageSpinLock)) { >>> 97 CpuPause (); >>> 98 } >>> 99 // >>> 100 // Initialize the serial port before dumping. >>> 101 // >>> 102 SerialPortInitialize (); >>> 103 // >>> 104 // Display ExceptionType, CPU information and Image information >>> 105 // >>> 106 DumpImageAndCpuContent (ExceptionType, SystemContext); >>> 107 // >>> 108 // Release Spinlock of output message >>> 109 // >>> 110 ReleaseSpinLock (&ExceptionHandlerData->DisplayMessageSpinLock); >>> 111 // >>> 112 // Enter a dead loop if needn't to execute old IDT handler further >>> 113 // >>> 114 if (ReservedVectors[ExceptionType].Attribute != EFI_VECTOR_HANDOFF_HOOK_BEFORE) { >>> -> 115 CpuDeadLoop (); >>> 116 } >>> 117 } >>> 118 } >>> 119 >>> (lldb) p ExceptionType >>> (EFI_EXCEPTION_TYPE) $0 = 0 >>> (lldb) p SystemContext.SystemContextX64->Rip >>> (UINT64) $1 = 0x0000000007a9cc38 >>> (lldb) p SystemContext.SystemContextX64->Rbp >>> (UINT64) $2 = 0x0000000007e8fc20 >>> (lldb) efi_backtrace --pc 0x0000000007a9cc38 --frame 0x0000000007e8fc20 --symbols >>> frame 0: 0x07a9cc38 BdsDxe:PlatformBootManagerWaitCallback + 35 at /Volumes/Case/UDK2018/OvmfPkg/Library/PlatformBootManagerLib/BdsPlatform.c:1646:37 >>> frame 1: 0x07a9e744 BdsDxe:BdsWait + 269 at /Volumes/Case/UDK2018/MdeModulePkg/Universal/BdsDxe/BdsEntry.c:344:3 >>> frame 2: 0x07a9dff9 BdsDxe:BdsEntry + 2620 at /Volumes/Case/UDK2018/MdeModulePkg/Universal/BdsDxe/BdsEntry.c:1002:5 >>> frame 3: 0x07eb367d DxeCore:DxeMain + 2680 at /Volumes/Case/UDK2018/MdeModulePkg/Core/Dxe/DxeMain/DxeMain.c:544:3 >>> frame 4: 0x07e943cb DxeCore:_ModuleEntryPoint + 20 at /Volumes/Case/UDK2018/MdePkg/Library/DxeCoreEntryPoint/DxeCoreEntryPoint.c:48:3 >>> frame 5: 0x07edc947 DxeIpl.dll`AsmEnableCache >>> frame 6: 0x07ee1e4e DxeIpl:HandOffToDxeCore + 509 at /Volumes/Case/UDK2018/MdeModulePkg/Core/DxeIplPeim/X64/DxeLoadFunc.c:113:3 >>> frame 7: 0x07ee0604 DxeIpl:DxeLoadCore + 1354 at /Volumes/Case/UDK2018/MdeModulePkg/Core/DxeIplPeim/DxeLoad.c:449:3 >>> frame 8: 0x07eeff2f PeiCore.dll`PeiCore.cold.3 + 847 >>> frame 9: 0x07ee9d04 PeiCore:PeiCore + 163 at /Volumes/Case/UDK2018/MdeModulePkg/Core/Pei/PeiMain/PeiMain.c:502:3 >>> frame 10: 0x0082c387 0x0082c387 >>> frame 11: 0x00825dd7 0x00825dd7 >>> frame 12: 0x0082ad27 0x0082ad27 >>> frame 13: 0x0082b3a8 0x0082b3a8 >>> frame 14: 0x0082bf23 0x0082bf23 >>> frame 15: 0x00825e24 0x00825e24 >>> frame 16: 0x00823af2 0x00823af2 >>> frame 17: 0xfffd1db8 SecMain:SecStartupPhase2 + 67 at /Volumes/Case/UDK2018/OvmfPkg/Sec/SecMain.c:858:3 >>> frame 18: 0xfffd1d67 SecMain:SecCoreStartupWithStack + 420 at /Volumes/Case/UDK2018/OvmfPkg/Sec/SecMain.c:821:3 >>> frame 19: 0xfffd1e14 SecMain:ProcessLibraryConstructorList + 0 at /Volumes/Case/UDK2018/Build/OvmfX64/DEBUG_XCODE5/X64/OvmfPkg/Sec/SecMain/DEBUG/AutoGen.c:201 >>> >>> (lldb) l /Volumes/Case/UDK2018/OvmfPkg/Library/PlatformBootManagerLib/BdsPlatform.c:1646 >>> 1646 (Timeout - TimeoutRemain) * 100 / Timeout, >>> 1647 0 >>> 1648 ); >>> 1649 } >>> 1650 >>> 1651 /** >>> 1652 The function is called when no boot option could be launched, >>> 1653 including platform recovery options and options pointing to applications >>> 1654 built into firmware volumes. >>> 1655 >>> (lldb) l /Volumes/Case/UDK2018/MdeModulePkg/Universal/BdsDxe/BdsEntry.c:344 >>> 344 PlatformBootManagerWaitCallback (0); >>> 345 DEBUG ((EFI_D_INFO, "[Bds]Exit the waiting!\n")); >>> 346 } >>> 347 >>> 348 /** >>> 349 Attempt to boot each boot option in the BootOptions array. >>> 350 >>> 351 @param BootOptions Input boot option array. >>> 352 @param BootOptionCount Input boot option count. >>> 353 @param BootManagerMenu Input boot manager menu. >>> 354 >>> >>> >>> Thanks, >>> >>> Andrew Fish >>> >>> >> >> >> [-- Attachment #2: Type: text/html, Size: 27212 bytes --] ^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [edk2-devel] OVMF is crashing for me in master 2019-10-11 1:19 ` [edk2-devel] " Liming Gao 2019-10-11 4:59 ` Andrew Fish @ 2019-10-11 11:50 ` Laszlo Ersek 2019-10-11 12:16 ` Pete Batard 2019-10-11 13:13 ` Andrew Fish 1 sibling, 2 replies; 10+ messages in thread From: Laszlo Ersek @ 2019-10-11 11:50 UTC (permalink / raw) To: devel, liming.gao, afish@apple.com, Pete Batard Hi, On 10/11/19 03:19, Liming Gao wrote: > Andrew: > I verify the change (2de1f611be06ded3a59726a4052a9039be7d459b > MdeModulePkg/BdsDxe: Also call PlatformBootManagerWaitCallback on 0) > in Emulator. > It works, because PCD value is set to 10 in Emulator. > > Before this change, if TimeOut PCD is zero, BdsEntry doesn't call > PlatformBootManagerWaitCallback(). > After this change, if TimeOut PCD is zero, BdsEntry still call > PlatformBootManagerWaitCallback(). So, it trigs this issue. I agree > your fix. > > Pete: > Will you contribute the patch to fix this hang issue in OVMF? So, when Pete submitted the BDS patch, I didn't test it, I only looked at the patch email. See my feedback here: http://mid.mail-archive.com/8bacbb53-98df-724e-b704-b5059d11e378@redhat.com https://edk2.groups.io/g/devel/message/48133 It seemed OK to me. In particular, I reasoned about (TimeoutRemain==0), and the patch seemed to do the right thing for that. Unfortunately, what I missed was the following case: - if PcdPlatformBootTimeOut is zero, then the patch by Pete does not simply make one more call to PlatformBootManagerWaitCallback(), with argument zero, but it makes the *ONLY* call to PlatformBootManagerWaitCallback(). I missed this because (like normal) the patch was sent with a 3-line context, and I didn't think it necessary to review the full function context. Here is the commit, with full function context: > diff --git a/MdeModulePkg/Universal/BdsDxe/BdsEntry.c b/MdeModulePkg/Universal/BdsDxe/BdsEntry.c > index f3d5e5ac0615..7968a58f3454 100644 > --- a/MdeModulePkg/Universal/BdsDxe/BdsEntry.c > +++ b/MdeModulePkg/Universal/BdsDxe/BdsEntry.c > @@ -310,47 +310,48 @@ VOID > BdsWait ( > IN EFI_EVENT HotkeyTriggered > ) > { > EFI_STATUS Status; > UINT16 TimeoutRemain; > > DEBUG ((EFI_D_INFO, "[Bds]BdsWait ...Zzzzzzzzzzzz...\n")); > > TimeoutRemain = PcdGet16 (PcdPlatformBootTimeOut); > while (TimeoutRemain != 0) { > DEBUG ((EFI_D_INFO, "[Bds]BdsWait(%d)..Zzzz...\n", (UINTN) TimeoutRemain)); > PlatformBootManagerWaitCallback (TimeoutRemain); > > BdsReadKeys (); // BUGBUG: Only reading can signal HotkeyTriggered > // Can be removed after all keyboard drivers invoke callback in timer callback. > > if (HotkeyTriggered != NULL) { > Status = BdsWaitForSingleEvent (HotkeyTriggered, EFI_TIMER_PERIOD_SECONDS (1)); > if (!EFI_ERROR (Status)) { > break; > } > } else { > gBS->Stall (1000000); > } > > // > // 0xffff means waiting forever > // BDS with no hotkey provided and 0xffff as timeout will "hang" in the loop > // > if (TimeoutRemain != 0xffff) { > TimeoutRemain--; > } > } > + PlatformBootManagerWaitCallback (0); > DEBUG ((EFI_D_INFO, "[Bds]Exit the waiting!\n")); > } We can see that the function used to handle the PcdPlatformBootTimeOut==0 situation well, and make *no* call to PlatformBootManagerWaitCallback(). The patch broke that behavior. Therefore, I disagree with the idea to fix this in OvmfPkg. Any number of platforms may exist that rely on PlatformBootManagerWaitCallback() not being called when PcdPlatformBootTimeOut is zero. (To name just one other example, ArmVirtPkg too is affected.) And for OVMF and ArmVirtPkg, it is definitely correct to *not* display any progress bar if PcdPlatformBootTimeOut is 0. Please consult the definition of the PCD in "MdePkg/MdePkg.dec": > ## The number of seconds that the firmware will wait before initiating the original default boot selection. > # A value of 0 indicates that the default boot selection is to be initiated immediately on boot. > # The value of 0xFFFF then firmware will wait for user input before booting. > # @Prompt Boot Timeout (s) > gEfiMdePkgTokenSpaceGuid.PcdPlatformBootTimeOut|0xffff|UINT16|0x0000002c Also see the specification of PlatformBootManagerWaitCallback(), in "MdeModulePkg/Include/Library/PlatformBootManagerLib.h": > /** > This function is called each second during the boot manager waits the timeout. > > @param TimeoutRemain The remaining timeout. > **/ > VOID > EFIAPI > PlatformBootManagerWaitCallback ( > UINT16 TimeoutRemain > ); According to the DEC file, there is no waiting if the PCD is zero. Therefore, if the PCD is zero, the function should not be called at all. There is another complication, namely, if the PCD is 0xFFFF. In this case, the loop goes on until a hotkey is pressed. In every iteration (that is, every second), PlatformBootManagerWaitCallback() is called with argument 0xFFFF, invariably. Clearly, this *cannot* cause a platform to display any progress *changes*. In the most common callback implementation, namely in the formula (Timeout - TimeoutRemain) * 100 / Timeout, it will mean (0xFFFF - 0xFFFF) * 100 / 0xFFFF, that is, "zero percent", in every iteration. Based on that, it looks wrong to suddenly call PlatformBootManagerWaitCallback() with a zero argument ("hundred percent completion"), after it's been called, let's say for a minute or more, with a constant 0xFFFF argument ("zero percent completion"), until the user finally presses a hotkey. Jumping from zero to 100% is discontiguous and doesn't appear helpful to me. Further yet, what if there is an actual progress bar and timeout (like 10 seconds), and the user presses a hotkey after 5 seconds? Should the progress bar jump to 100% at once? I wouldn't think so. Therefore, I claim that the right fix is: > diff --git a/MdeModulePkg/Universal/BdsDxe/BdsEntry.c b/MdeModulePkg/Universal/BdsDxe/BdsEntry.c > index 7968a58f3454..d12829afeb8b 100644 > --- a/MdeModulePkg/Universal/BdsDxe/BdsEntry.c > +++ b/MdeModulePkg/Universal/BdsDxe/BdsEntry.c > @@ -341,7 +341,16 @@ BdsWait ( > TimeoutRemain--; > } > } > - PlatformBootManagerWaitCallback (0); > + // > + // If the platform configured a nonzero and finite time-out, and we have > + // actually reached that, report 100% completion to the platform. > + // > + // Note that the (TimeoutRemain == 0) condition excludes > + // PcdPlatformBootTimeOut=0xFFFF, and that's deliberate. > + // > + if (PcdGet16 (PcdPlatformBootTimeOut) != 0 && TimeoutRemain == 0) { > + PlatformBootManagerWaitCallback (0); > + } > DEBUG ((EFI_D_INFO, "[Bds]Exit the waiting!\n")); > } > Thanks! Laszlo ^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [edk2-devel] OVMF is crashing for me in master 2019-10-11 11:50 ` Laszlo Ersek @ 2019-10-11 12:16 ` Pete Batard 2019-10-11 13:13 ` Andrew Fish 1 sibling, 0 replies; 10+ messages in thread From: Pete Batard @ 2019-10-11 12:16 UTC (permalink / raw) To: Laszlo Ersek, devel, liming.gao, afish@apple.com Hi Lazlo, On 2019.10.11 12:50, Laszlo Ersek wrote: > Hi, > > On 10/11/19 03:19, Liming Gao wrote: >> Andrew: >> I verify the change (2de1f611be06ded3a59726a4052a9039be7d459b >> MdeModulePkg/BdsDxe: Also call PlatformBootManagerWaitCallback on 0) >> in Emulator. >> It works, because PCD value is set to 10 in Emulator. >> >> Before this change, if TimeOut PCD is zero, BdsEntry doesn't call >> PlatformBootManagerWaitCallback(). >> After this change, if TimeOut PCD is zero, BdsEntry still call >> PlatformBootManagerWaitCallback(). So, it trigs this issue. I agree >> your fix. >> >> Pete: >> Will you contribute the patch to fix this hang issue in OVMF? > > So, when Pete submitted the BDS patch, I didn't test it, I only looked > at the patch email. See my feedback here: > > http://mid.mail-archive.com/8bacbb53-98df-724e-b704-b5059d11e378@redhat.com > https://edk2.groups.io/g/devel/message/48133 > > It seemed OK to me. In particular, I reasoned about (TimeoutRemain==0), > and the patch seemed to do the right thing for that. > > Unfortunately, what I missed was the following case: > > - if PcdPlatformBootTimeOut is zero, then the patch by Pete does not > simply make one more call to PlatformBootManagerWaitCallback(), with > argument zero, but it makes the *ONLY* call to > PlatformBootManagerWaitCallback(). > > I missed this because (like normal) the patch was sent with a 3-line > context, and I didn't think it necessary to review the full function > context. > > Here is the commit, with full function context: > >> diff --git a/MdeModulePkg/Universal/BdsDxe/BdsEntry.c b/MdeModulePkg/Universal/BdsDxe/BdsEntry.c >> index f3d5e5ac0615..7968a58f3454 100644 >> --- a/MdeModulePkg/Universal/BdsDxe/BdsEntry.c >> +++ b/MdeModulePkg/Universal/BdsDxe/BdsEntry.c >> @@ -310,47 +310,48 @@ VOID >> BdsWait ( >> IN EFI_EVENT HotkeyTriggered >> ) >> { >> EFI_STATUS Status; >> UINT16 TimeoutRemain; >> >> DEBUG ((EFI_D_INFO, "[Bds]BdsWait ...Zzzzzzzzzzzz...\n")); >> >> TimeoutRemain = PcdGet16 (PcdPlatformBootTimeOut); >> while (TimeoutRemain != 0) { >> DEBUG ((EFI_D_INFO, "[Bds]BdsWait(%d)..Zzzz...\n", (UINTN) TimeoutRemain)); >> PlatformBootManagerWaitCallback (TimeoutRemain); >> >> BdsReadKeys (); // BUGBUG: Only reading can signal HotkeyTriggered >> // Can be removed after all keyboard drivers invoke callback in timer callback. >> >> if (HotkeyTriggered != NULL) { >> Status = BdsWaitForSingleEvent (HotkeyTriggered, EFI_TIMER_PERIOD_SECONDS (1)); >> if (!EFI_ERROR (Status)) { >> break; >> } >> } else { >> gBS->Stall (1000000); >> } >> >> // >> // 0xffff means waiting forever >> // BDS with no hotkey provided and 0xffff as timeout will "hang" in the loop >> // >> if (TimeoutRemain != 0xffff) { >> TimeoutRemain--; >> } >> } >> + PlatformBootManagerWaitCallback (0); >> DEBUG ((EFI_D_INFO, "[Bds]Exit the waiting!\n")); >> } > > We can see that the function used to handle the > PcdPlatformBootTimeOut==0 situation well, and make *no* call to > PlatformBootManagerWaitCallback(). The patch broke that behavior. > > Therefore, I disagree with the idea to fix this in OvmfPkg. Any number > of platforms may exist that rely on PlatformBootManagerWaitCallback() > not being called when PcdPlatformBootTimeOut is zero. > > (To name just one other example, ArmVirtPkg too is affected.) > > And for OVMF and ArmVirtPkg, it is definitely correct to *not* display > any progress bar if PcdPlatformBootTimeOut is 0. > > Please consult the definition of the PCD in "MdePkg/MdePkg.dec": > >> ## The number of seconds that the firmware will wait before initiating the original default boot selection. >> # A value of 0 indicates that the default boot selection is to be initiated immediately on boot. >> # The value of 0xFFFF then firmware will wait for user input before booting. >> # @Prompt Boot Timeout (s) >> gEfiMdePkgTokenSpaceGuid.PcdPlatformBootTimeOut|0xffff|UINT16|0x0000002c > > Also see the specification of PlatformBootManagerWaitCallback(), in > "MdeModulePkg/Include/Library/PlatformBootManagerLib.h": > >> /** >> This function is called each second during the boot manager waits the timeout. >> >> @param TimeoutRemain The remaining timeout. >> **/ >> VOID >> EFIAPI >> PlatformBootManagerWaitCallback ( >> UINT16 TimeoutRemain >> ); > > According to the DEC file, there is no waiting if the PCD is zero. > Therefore, if the PCD is zero, the function should not be called at all. > > > There is another complication, namely, if the PCD is 0xFFFF. In this > case, the loop goes on until a hotkey is pressed. In every iteration > (that is, every second), PlatformBootManagerWaitCallback() is called > with argument 0xFFFF, invariably. Clearly, this *cannot* cause a > platform to display any progress *changes*. In the most common callback > implementation, namely in the formula > > (Timeout - TimeoutRemain) * 100 / Timeout, > > it will mean > > (0xFFFF - 0xFFFF) * 100 / 0xFFFF, > > that is, "zero percent", in every iteration. > > Based on that, it looks wrong to suddenly call > PlatformBootManagerWaitCallback() with a zero argument ("hundred percent > completion"), after it's been called, let's say for a minute or more, > with a constant 0xFFFF argument ("zero percent completion"), until the > user finally presses a hotkey. > > Jumping from zero to 100% is discontiguous and doesn't appear helpful to > me. > > > Further yet, what if there is an actual progress bar and timeout (like > 10 seconds), and the user presses a hotkey after 5 seconds? Should the > progress bar jump to 100% at once? I wouldn't think so. > > > Therefore, I claim that the right fix is: > >> diff --git a/MdeModulePkg/Universal/BdsDxe/BdsEntry.c b/MdeModulePkg/Universal/BdsDxe/BdsEntry.c >> index 7968a58f3454..d12829afeb8b 100644 >> --- a/MdeModulePkg/Universal/BdsDxe/BdsEntry.c >> +++ b/MdeModulePkg/Universal/BdsDxe/BdsEntry.c >> @@ -341,7 +341,16 @@ BdsWait ( >> TimeoutRemain--; >> } >> } >> - PlatformBootManagerWaitCallback (0); >> + // >> + // If the platform configured a nonzero and finite time-out, and we have >> + // actually reached that, report 100% completion to the platform. >> + // >> + // Note that the (TimeoutRemain == 0) condition excludes >> + // PcdPlatformBootTimeOut=0xFFFF, and that's deliberate. >> + // >> + if (PcdGet16 (PcdPlatformBootTimeOut) != 0 && TimeoutRemain == 0) { >> + PlatformBootManagerWaitCallback (0); >> + } >> DEBUG ((EFI_D_INFO, "[Bds]Exit the waiting!\n")); >> } >> I agree with the analysis and the proposed fix. My earlier patch was indeed altering existing behaviour when PcdPlatformBootTimeOut was 0, and I completely missed that. Also, apologies for not replying to the direct request you sent to me earlier. The e-mail client I use does not currently deduplicate messages that are sent both to the list as well as directly to me as CC, so I only get one copy in the list which makes these requests easy to miss. I'll try to fix that. Many thanks for looking into this! Regards, /Pete > > Thanks! > Laszlo > ^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [edk2-devel] OVMF is crashing for me in master 2019-10-11 11:50 ` Laszlo Ersek 2019-10-11 12:16 ` Pete Batard @ 2019-10-11 13:13 ` Andrew Fish 2019-10-11 16:33 ` Laszlo Ersek 1 sibling, 1 reply; 10+ messages in thread From: Andrew Fish @ 2019-10-11 13:13 UTC (permalink / raw) To: devel, lersek; +Cc: liming.gao, Pete Batard [-- Attachment #1: Type: text/plain, Size: 10066 bytes --] > On Oct 11, 2019, at 4:50 AM, Laszlo Ersek <lersek@redhat.com> wrote: > > Hi, > > On 10/11/19 03:19, Liming Gao wrote: >> Andrew: >> I verify the change (2de1f611be06ded3a59726a4052a9039be7d459b >> MdeModulePkg/BdsDxe: Also call PlatformBootManagerWaitCallback on 0) >> in Emulator. >> It works, because PCD value is set to 10 in Emulator. >> >> Before this change, if TimeOut PCD is zero, BdsEntry doesn't call >> PlatformBootManagerWaitCallback(). >> After this change, if TimeOut PCD is zero, BdsEntry still call >> PlatformBootManagerWaitCallback(). So, it trigs this issue. I agree >> your fix. >> >> Pete: >> Will you contribute the patch to fix this hang issue in OVMF? > > So, when Pete submitted the BDS patch, I didn't test it, I only looked > at the patch email. See my feedback here: > > http://mid.mail-archive.com/8bacbb53-98df-724e-b704-b5059d11e378@redhat.com <http://mid.mail-archive.com/8bacbb53-98df-724e-b704-b5059d11e378@redhat.com> > https://edk2.groups.io/g/devel/message/48133 <https://edk2.groups.io/g/devel/message/48133> > > It seemed OK to me. In particular, I reasoned about (TimeoutRemain==0), > and the patch seemed to do the right thing for that. > > Unfortunately, what I missed was the following case: > > - if PcdPlatformBootTimeOut is zero, then the patch by Pete does not > simply make one more call to PlatformBootManagerWaitCallback(), with > argument zero, but it makes the *ONLY* call to > PlatformBootManagerWaitCallback(). > > I missed this because (like normal) the patch was sent with a 3-line > context, and I didn't think it necessary to review the full function > context. > > Here is the commit, with full function context: > >> diff --git a/MdeModulePkg/Universal/BdsDxe/BdsEntry.c b/MdeModulePkg/Universal/BdsDxe/BdsEntry.c >> index f3d5e5ac0615..7968a58f3454 100644 >> --- a/MdeModulePkg/Universal/BdsDxe/BdsEntry.c >> +++ b/MdeModulePkg/Universal/BdsDxe/BdsEntry.c >> @@ -310,47 +310,48 @@ VOID >> BdsWait ( >> IN EFI_EVENT HotkeyTriggered >> ) >> { >> EFI_STATUS Status; >> UINT16 TimeoutRemain; >> >> DEBUG ((EFI_D_INFO, "[Bds]BdsWait ...Zzzzzzzzzzzz...\n")); >> >> TimeoutRemain = PcdGet16 (PcdPlatformBootTimeOut); >> while (TimeoutRemain != 0) { >> DEBUG ((EFI_D_INFO, "[Bds]BdsWait(%d)..Zzzz...\n", (UINTN) TimeoutRemain)); >> PlatformBootManagerWaitCallback (TimeoutRemain); >> >> BdsReadKeys (); // BUGBUG: Only reading can signal HotkeyTriggered >> // Can be removed after all keyboard drivers invoke callback in timer callback. >> >> if (HotkeyTriggered != NULL) { >> Status = BdsWaitForSingleEvent (HotkeyTriggered, EFI_TIMER_PERIOD_SECONDS (1)); >> if (!EFI_ERROR (Status)) { >> break; >> } >> } else { >> gBS->Stall (1000000); >> } >> >> // >> // 0xffff means waiting forever >> // BDS with no hotkey provided and 0xffff as timeout will "hang" in the loop >> // >> if (TimeoutRemain != 0xffff) { >> TimeoutRemain--; >> } >> } >> + PlatformBootManagerWaitCallback (0); >> DEBUG ((EFI_D_INFO, "[Bds]Exit the waiting!\n")); >> } > > We can see that the function used to handle the > PcdPlatformBootTimeOut==0 situation well, and make *no* call to > PlatformBootManagerWaitCallback(). The patch broke that behavior. > > Therefore, I disagree with the idea to fix this in OvmfPkg. Any number > of platforms may exist that rely on PlatformBootManagerWaitCallback() > not being called when PcdPlatformBootTimeOut is zero. > > (To name just one other example, ArmVirtPkg too is affected.) > > And for OVMF and ArmVirtPkg, it is definitely correct to *not* display > any progress bar if PcdPlatformBootTimeOut is 0. > > Please consult the definition of the PCD in "MdePkg/MdePkg.dec": > >> ## The number of seconds that the firmware will wait before initiating the original default boot selection. >> # A value of 0 indicates that the default boot selection is to be initiated immediately on boot. >> # The value of 0xFFFF then firmware will wait for user input before booting. >> # @Prompt Boot Timeout (s) >> gEfiMdePkgTokenSpaceGuid.PcdPlatformBootTimeOut|0xffff|UINT16|0x0000002c > > Also see the specification of PlatformBootManagerWaitCallback(), in > "MdeModulePkg/Include/Library/PlatformBootManagerLib.h": > >> /** >> This function is called each second during the boot manager waits the timeout. >> >> @param TimeoutRemain The remaining timeout. >> **/ >> VOID >> EFIAPI >> PlatformBootManagerWaitCallback ( >> UINT16 TimeoutRemain >> ); > > According to the DEC file, there is no waiting if the PCD is zero. > Therefore, if the PCD is zero, the function should not be called at all. > > > There is another complication, namely, if the PCD is 0xFFFF. In this > case, the loop goes on until a hotkey is pressed. In every iteration > (that is, every second), PlatformBootManagerWaitCallback() is called > with argument 0xFFFF, invariably. Clearly, this *cannot* cause a > platform to display any progress *changes*. In the most common callback > implementation, namely in the formula > > (Timeout - TimeoutRemain) * 100 / Timeout, > > it will mean > > (0xFFFF - 0xFFFF) * 100 / 0xFFFF, > > that is, "zero percent", in every iteration. > > Based on that, it looks wrong to suddenly call > PlatformBootManagerWaitCallback() with a zero argument ("hundred percent > completion"), after it's been called, let's say for a minute or more, > with a constant 0xFFFF argument ("zero percent completion"), until the > user finally presses a hotkey. > > Jumping from zero to 100% is discontiguous and doesn't appear helpful to > me. > > > Further yet, what if there is an actual progress bar and timeout (like > 10 seconds), and the user presses a hotkey after 5 seconds? Should the > progress bar jump to 100% at once? I wouldn't think so. > Laszlo, I'm with Pete on this as my expectation would be the progress bar completes when you are done. I'd also point out that a common progress bar UI implementation is to show the area that is going to be updated. I don't think our UI does that, but it could get updated at some point. Thus I would posit that if PlatformBootManagerWaitCallback() is called by passing in PcdPlatformBootTimeOut you should always call PlatformBootManagerWaitCallback() with zero to terminate the progress bar. What makes sense to me is to skip the UI if PcdPlatformBootTimeOut is zero. The PlatformBootManagerWaitCallback (0) is only really needed if PlatformBootManagerWaitCallback (0) has not been called (TimeoutRemain != 0). diff --git a/MdeModulePkg/Universal/BdsDxe/BdsEntry.c b/MdeModulePkg/Universal/BdsDxe/BdsEntry.c index 7968a58f34..fd551d17e1 100644 --- a/MdeModulePkg/Universal/BdsDxe/BdsEntry.c +++ b/MdeModulePkg/Universal/BdsDxe/BdsEntry.c @@ -317,31 +317,35 @@ BdsWait ( DEBUG ((EFI_D_INFO, "[Bds]BdsWait ...Zzzzzzzzzzzz...\n")); TimeoutRemain = PcdGet16 (PcdPlatformBootTimeOut); - while (TimeoutRemain != 0) { - DEBUG ((EFI_D_INFO, "[Bds]BdsWait(%d)..Zzzz...\n", (UINTN) TimeoutRemain)); - PlatformBootManagerWaitCallback (TimeoutRemain); + if (TimeoutRemain != 0) { + while (TimeoutRemain != 0) { + DEBUG ((EFI_D_INFO, "[Bds]BdsWait(%d)..Zzzz...\n", (UINTN) TimeoutRemain)); + PlatformBootManagerWaitCallback (TimeoutRemain); - BdsReadKeys (); // BUGBUG: Only reading can signal HotkeyTriggered - // Can be removed after all keyboard drivers invoke callback in timer callback. + BdsReadKeys (); // BUGBUG: Only reading can signal HotkeyTriggered + // Can be removed after all keyboard drivers invoke callback in timer callback. - if (HotkeyTriggered != NULL) { - Status = BdsWaitForSingleEvent (HotkeyTriggered, EFI_TIMER_PERIOD_SECONDS (1)); - if (!EFI_ERROR (Status)) { - break; + if (HotkeyTriggered != NULL) { + Status = BdsWaitForSingleEvent (HotkeyTriggered, EFI_TIMER_PERIOD_SECONDS (1)); + if (!EFI_ERROR (Status)) { + break; + } + } else { + gBS->Stall (1000000); } - } else { - gBS->Stall (1000000); - } - // - // 0xffff means waiting forever - // BDS with no hotkey provided and 0xffff as timeout will "hang" in the loop - // - if (TimeoutRemain != 0xffff) { - TimeoutRemain--; + // + // 0xffff means waiting forever + // BDS with no hotkey provided and 0xffff as timeout will "hang" in the loop + // + if (TimeoutRemain != 0xffff) { + TimeoutRemain--; + } + } + if (TimeoutRemain != 0) { + PlatformBootManagerWaitCallback (0); } } - PlatformBootManagerWaitCallback (0); DEBUG ((EFI_D_INFO, "[Bds]Exit the waiting!\n")); } Thanks, Andrew Fish > > Therefore, I claim that the right fix is: > >> diff --git a/MdeModulePkg/Universal/BdsDxe/BdsEntry.c b/MdeModulePkg/Universal/BdsDxe/BdsEntry.c >> index 7968a58f3454..d12829afeb8b 100644 >> --- a/MdeModulePkg/Universal/BdsDxe/BdsEntry.c >> +++ b/MdeModulePkg/Universal/BdsDxe/BdsEntry.c >> @@ -341,7 +341,16 @@ BdsWait ( >> TimeoutRemain--; >> } >> } >> - PlatformBootManagerWaitCallback (0); >> + // >> + // If the platform configured a nonzero and finite time-out, and we have >> + // actually reached that, report 100% completion to the platform. >> + // >> + // Note that the (TimeoutRemain == 0) condition excludes >> + // PcdPlatformBootTimeOut=0xFFFF, and that's deliberate. >> + // >> + if (PcdGet16 (PcdPlatformBootTimeOut) != 0 && TimeoutRemain == 0) { >> + PlatformBootManagerWaitCallback (0); >> + } >> DEBUG ((EFI_D_INFO, "[Bds]Exit the waiting!\n")); >> } >> > > Thanks! > Laszlo > > [-- Attachment #2: Type: text/html, Size: 79693 bytes --] ^ permalink raw reply related [flat|nested] 10+ messages in thread
* Re: [edk2-devel] OVMF is crashing for me in master 2019-10-11 13:13 ` Andrew Fish @ 2019-10-11 16:33 ` Laszlo Ersek 2019-10-11 19:07 ` Andrew Fish 0 siblings, 1 reply; 10+ messages in thread From: Laszlo Ersek @ 2019-10-11 16:33 UTC (permalink / raw) To: Andrew Fish, devel; +Cc: liming.gao, Pete Batard Hi Andrew, On 10/11/19 15:13, Andrew Fish wrote: > I'm with Pete on this as my expectation would be the progress bar > completes when you are done. I'd also point out that a common progress > bar UI implementation is to show the area that is going to be updated. > I don't think our UI does that, but it could get updated at some > point. Thus I would posit that if PlatformBootManagerWaitCallback() is > called by passing in PcdPlatformBootTimeOut you should always call > PlatformBootManagerWaitCallback() with zero to terminate the progress > bar. OK. > What makes sense to me is to skip the UI if PcdPlatformBootTimeOut is > zero. The PlatformBootManagerWaitCallback (0) is only really needed if > PlatformBootManagerWaitCallback (0) has not been called (TimeoutRemain > != 0). Let me paste your patch below, formatted with the "--ignore-space-change" option (it hides changes due to simple re-indentation of code): > diff --git a/MdeModulePkg/Universal/BdsDxe/BdsEntry.c b/MdeModulePkg/Universal/BdsDxe/BdsEntry.c > index 7968a58f3454..fd551d17e15d 100644 > --- a/MdeModulePkg/Universal/BdsDxe/BdsEntry.c > +++ b/MdeModulePkg/Universal/BdsDxe/BdsEntry.c > @@ -310,48 +310,52 @@ VOID > BdsWait ( > IN EFI_EVENT HotkeyTriggered > ) > { > EFI_STATUS Status; > UINT16 TimeoutRemain; > > DEBUG ((EFI_D_INFO, "[Bds]BdsWait ...Zzzzzzzzzzzz...\n")); > > TimeoutRemain = PcdGet16 (PcdPlatformBootTimeOut); > + if (TimeoutRemain != 0) { > while (TimeoutRemain != 0) { > DEBUG ((EFI_D_INFO, "[Bds]BdsWait(%d)..Zzzz...\n", (UINTN) TimeoutRemain)); > PlatformBootManagerWaitCallback (TimeoutRemain); > > BdsReadKeys (); // BUGBUG: Only reading can signal HotkeyTriggered > // Can be removed after all keyboard drivers invoke callback in timer callback. > > if (HotkeyTriggered != NULL) { > Status = BdsWaitForSingleEvent (HotkeyTriggered, EFI_TIMER_PERIOD_SECONDS (1)); > if (!EFI_ERROR (Status)) { > break; > } > } else { > gBS->Stall (1000000); > } > > // > // 0xffff means waiting forever > // BDS with no hotkey provided and 0xffff as timeout will "hang" in the loop > // > if (TimeoutRemain != 0xffff) { > TimeoutRemain--; > } > } > + if (TimeoutRemain != 0) { > PlatformBootManagerWaitCallback (0); > + } > + } > DEBUG ((EFI_D_INFO, "[Bds]Exit the waiting!\n")); > } This would solve the (PcdPlatformBootTimeOut==0) case well. However, it would regress Pete's use case. Namely, if you allow the loop to time out (the "while" statement sees a zero "TimeoutRemain"), then the final PlatformBootManagerWaitCallback (0) is skipped. And that's the problem Pete intended to fix in the first place: when the loop times out, PlatformBootManagerWaitCallback (0) is *never* called, inside the loop. So we start booting e.g. an OS, without the progress bar filling the screen to the right edge. I think if we eliminate the *inner* "if" statement -- call PlatformBootManagerWaitCallback (0) unconditionally --, and preserve the outer "if" statement, it should work. Thanks Laszlo ^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [edk2-devel] OVMF is crashing for me in master 2019-10-11 16:33 ` Laszlo Ersek @ 2019-10-11 19:07 ` Andrew Fish 0 siblings, 0 replies; 10+ messages in thread From: Andrew Fish @ 2019-10-11 19:07 UTC (permalink / raw) To: devel, lersek; +Cc: liming.gao, Pete Batard > On Oct 11, 2019, at 9:33 AM, Laszlo Ersek <lersek@redhat.com> wrote: > > Hi Andrew, > > On 10/11/19 15:13, Andrew Fish wrote: > >> I'm with Pete on this as my expectation would be the progress bar >> completes when you are done. I'd also point out that a common progress >> bar UI implementation is to show the area that is going to be updated. >> I don't think our UI does that, but it could get updated at some >> point. Thus I would posit that if PlatformBootManagerWaitCallback() is >> called by passing in PcdPlatformBootTimeOut you should always call >> PlatformBootManagerWaitCallback() with zero to terminate the progress >> bar. > > OK. > >> What makes sense to me is to skip the UI if PcdPlatformBootTimeOut is >> zero. The PlatformBootManagerWaitCallback (0) is only really needed if >> PlatformBootManagerWaitCallback (0) has not been called (TimeoutRemain >> != 0). > > Let me paste your patch below, formatted with the > "--ignore-space-change" option (it hides changes due to simple > re-indentation of code): > >> diff --git a/MdeModulePkg/Universal/BdsDxe/BdsEntry.c b/MdeModulePkg/Universal/BdsDxe/BdsEntry.c >> index 7968a58f3454..fd551d17e15d 100644 >> --- a/MdeModulePkg/Universal/BdsDxe/BdsEntry.c >> +++ b/MdeModulePkg/Universal/BdsDxe/BdsEntry.c >> @@ -310,48 +310,52 @@ VOID >> BdsWait ( >> IN EFI_EVENT HotkeyTriggered >> ) >> { >> EFI_STATUS Status; >> UINT16 TimeoutRemain; >> >> DEBUG ((EFI_D_INFO, "[Bds]BdsWait ...Zzzzzzzzzzzz...\n")); >> >> TimeoutRemain = PcdGet16 (PcdPlatformBootTimeOut); >> + if (TimeoutRemain != 0) { >> while (TimeoutRemain != 0) { >> DEBUG ((EFI_D_INFO, "[Bds]BdsWait(%d)..Zzzz...\n", (UINTN) TimeoutRemain)); >> PlatformBootManagerWaitCallback (TimeoutRemain); >> >> BdsReadKeys (); // BUGBUG: Only reading can signal HotkeyTriggered >> // Can be removed after all keyboard drivers invoke callback in timer callback. >> >> if (HotkeyTriggered != NULL) { >> Status = BdsWaitForSingleEvent (HotkeyTriggered, EFI_TIMER_PERIOD_SECONDS (1)); >> if (!EFI_ERROR (Status)) { >> break; >> } >> } else { >> gBS->Stall (1000000); >> } >> >> // >> // 0xffff means waiting forever >> // BDS with no hotkey provided and 0xffff as timeout will "hang" in the loop >> // >> if (TimeoutRemain != 0xffff) { >> TimeoutRemain--; >> } >> } >> + if (TimeoutRemain != 0) { >> PlatformBootManagerWaitCallback (0); >> + } >> + } >> DEBUG ((EFI_D_INFO, "[Bds]Exit the waiting!\n")); >> } > > This would solve the (PcdPlatformBootTimeOut==0) case well. > > However, it would regress Pete's use case. Namely, if you allow the loop > to time out (the "while" statement sees a zero "TimeoutRemain"), then > the final PlatformBootManagerWaitCallback (0) is skipped. > > And that's the problem Pete intended to fix in the first place: when the > loop times out, PlatformBootManagerWaitCallback (0) is *never* called, > inside the loop. So we start booting e.g. an OS, without the progress > bar filling the screen to the right edge. > > I think if we eliminate the *inner* "if" statement -- call > PlatformBootManagerWaitCallback (0) unconditionally --, and preserve the > outer "if" statement, it should work. > Laszlo, Good point. I was trying to prevent 2 calls with 0 but now I notice that is not possible in the while loop. So I agree with your suggestion. I also like Pete's idea of adding the error check in PlatformBootManagerWaitCallback(). Thanks, Andrew Fish > Thanks > Laszlo > > > ^ permalink raw reply [flat|nested] 10+ messages in thread
end of thread, other threads:[~2019-10-11 19:07 UTC | newest] Thread overview: 10+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2019-10-10 21:12 OVMF is crashing for me in master Andrew Fish 2019-10-11 1:19 ` [edk2-devel] " Liming Gao 2019-10-11 4:59 ` Andrew Fish 2019-10-11 11:53 ` Laszlo Ersek 2019-10-11 12:49 ` Andrew Fish 2019-10-11 11:50 ` Laszlo Ersek 2019-10-11 12:16 ` Pete Batard 2019-10-11 13:13 ` Andrew Fish 2019-10-11 16:33 ` Laszlo Ersek 2019-10-11 19:07 ` Andrew Fish
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox