edk2-stable202205 - Issue with source level debugging of OVMF with QEMU and Intel UDK Debugger Tool v1.5


Ilya Somkin
 

Hello,

Don't really know whether similar issue was already reported in the past, but:

I faced it while was following through the arcticle "How to debug OVMF with QEMU using WinDbg" (https://github.com/tianocore/tianocore.github.io/wiki/How-to-debug-OVMF-with-QEMU-using-WinDbg).

Versions used:
QEMU v7.0.0,
WinDbg 6.3.9600.17298 X86,
Intel UDK Debugger Tool v1.5.

Script used to run debug session:
set EDKII_BUILD_DIR=D:\github_repos\Edk2Clean\edk2-stable202205\Build
set ARCH=X64
set TARGET=NOOPT
set TOOLCHAIN=VS2019

set PUTTY_PATH=C:\Program Files\PuTTY

set UDK_PATH=C:\Program Files (x86)\Intel\Intel(R) UEFI Development Kit Debugger Tool

set QEMU_PATH=C:\Program Files\qemu
set QEMU_EXECUTABLE=qemu-system-x86_64.exe

start "Monitor" /B "%PUTTY_PATH%\putty.exe" telnet://localhost:20717
start "Debugger" /B "%UDK_PATH%\eXdi.exe" /LaunchWinDbg
start "Console" /B "%PUTTY_PATH%\putty.exe" telnet://localhost:20715

start "QEMU" /B "%QEMU_PATH%\%QEMU_EXECUTABLE%" ^
-machine q35,smm=on,accel=tcg -cpu Nehalem ^
-global ICH9-LPC.disable_s3=1 ^
-drive if=pflash,format=raw,unit=0,file=%EDKII_BUILD_DIR%\Ovmf%ARCH%\%TARGET%_%TOOLCHAIN%\FV\OVMF_CODE.fd,readonly=on ^
-drive if=pflash,format=raw,unit=1,file=%EDKII_BUILD_DIR%\Ovmf%ARCH%\%TARGET%_%TOOLCHAIN%\FV\OVMF_VARS.fd ^
-monitor tcp:localhost:20717,server ^
-serial tcp:localhost:20716,server

Serial output:
SecCoreStartupWithStack(0xFFFCC000, 0x820000)
ASSERT [SecMain] d:\github_repos\edk2clean\edk2-stable202205\MdePkg\Library\BasePcdLibNull\PcdLib.c(95): ((BOOLEAN)(0==1))

The same ASSERT applies to current edk2-master (commit 19cbfaa4319edabf5feb4e9d867f042c2d5e72b6 (HEAD -> master, origin/master, origin/HEAD)).
edk2-stable202202 runs w/o any ASSERT messages straight to the shell.

Seems like above ASSERT is caused by following code in SourceLevelDebugPkg\Library\DebugAgent\DebugAgentCommon\DebugTimer.c:
ApicTimerFrequency = PcdGet32 (PcdFSBClock) / (UINT32)ApicTimerDivisor;

Previously PcdFSBClock was moved to Dynamic in commit 44ad51d6b19aa20f028ad630635818daa8b94e90, which resulted in using LibPcdGet32 from PcdLib|MdePkg/Library/BasePcdLibNull/BasePcdLibNull.inf.

edk2-[stable202205/master]\Build\OvmfX64\NOOPT_VS2019\X64\SourceLevelDebugPkg\Library\DebugAgent\SecPeiDebugAgentLib\DEBUG\AutoGen.h:
...
#define _PCD_GET_MODE_32_PcdFSBClock LibPcdGet32(_PCD_TOKEN_PcdFSBClock)
...

edk2-stable202202\Build\OvmfX64\NOOPT_VS2019\X64\SourceLevelDebugPkg\Library\DebugAgent\SecPeiDebugAgentLib\DEBUG\AutoGen.h:
...
extern const UINT32 _gPcd_FixedAtBuild_PcdFSBClock;
#define _PCD_GET_MODE_32_PcdFSBClock _gPcd_FixedAtBuild_PcdFSBClock
//#define _PCD_SET_MODE_32_PcdFSBClock ASSERT(FALSE) // It is not allowed to set value for a FIXED_AT_BUILD PCD
#define _PCD_VALUE_PcdFSBClock 200000000
...

Moving back PcdFSBClock to [PcdsFixedAtBuild] in OvmfPkgX64.dsc and MdePkg.dec allows QEMU to run until the next ASSERT message:
...
ASSERT_EFI_ERROR (Status = Unsupported)
ASSERT [LocalApicTimerDxe] d:\github_repos\edk2clean\edk2-stable202205\OvmfPkg\LocalApicTimerDxe\LocalApicTimerDxe.c(343): !(((INTN)(RETURN_STATUS)(Status)) < 0)
...

Caused by following code in edk2-stable202205\OvmfPkg\LocalApicTimerDxe\LocalApicTimerDxe.c:
...
//
// Install interrupt handler for Local APIC Timer
//
Status = mCpu->RegisterInterruptHandler (
mCpu,
LOCAL_APIC_TIMER_VECTOR, // Vector 32
TimerInterruptHandler
);
ASSERT_EFI_ERROR (Status);
...

EFI_UNSUPPORTED returned in edk2-stable202205\UefiCpuPkg\Library\CpuExceptionHandlerLib\PeiDxeSmmCpuException.c:
...
if ((InterruptType < 0) || (InterruptType >= (EFI_EXCEPTION_TYPE)EnabledInterruptNum) ||
(ReservedVectors[InterruptType].Attribute == EFI_VECTOR_HANDOFF_DO_NOT_HOOK)) // third condition evaluates to TRUE
{
return EFI_UNSUPPORTED;
}
...

mVectorHandoffInfoDebugAgent[] lists Vector 32 as EFI_VECTOR_HANDOFF_DO_NOT_HOOK in
edk2-stable202205\SourceLevelDebugPkg\Library\DebugAgent\DebugAgentCommon\DebugAgent.c:
...
//
// Vector Handoff Info list used by Debug Agent for persist
//
GLOBAL_REMOVE_IF_UNREFERENCED EFI_VECTOR_HANDOFF_INFO mVectorHandoffInfoDebugAgent[] = {
...
{
DEBUG_TIMER_VECTOR, // Vector 32
EFI_VECTOR_HANDOFF_DO_NOT_HOOK,
EFI_DEBUG_AGENT_GUID
},
...
Commenting "ASSERT_EFI_ERROR (Status);" allows to continue booting.

Could anybody please confirm/clarify or is it just me who makes it wrong/complicated?


Ilya Somkin
 

Command used to build FD image:
build -n 7 -a X64 -p OvmfPkg\OvmfPkgX64.dsc -b NOOPT -t VS2019 -D DEBUG_ON_SERIAL_PORT -D SOURCE_DEBUG_ENABLE=TRUE -D SMM_REQUIRE


Andrew Fish
 

Please file a BZ: https://bugzilla.tianocore.org/

The non-Windows builds use the gdb-remote stub from QEMU and do not need DEBUG_ON_SERIAL_PORT to source level debug. So maybe this has rotted out.

Thanks,

Andrew Fish

On Aug 8, 2022, at 1:27 PM, Ilya Somkin <ilya.somkin@...> wrote:

Command used to build FD image:
build -n 7 -a X64 -p OvmfPkg\OvmfPkgX64.dsc -b NOOPT -t VS2019 -D DEBUG_ON_SERIAL_PORT -D SOURCE_DEBUG_ENABLE=TRUE -D SMM_REQUIRE