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


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





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


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?