emulation/qemu-q35: fix S3 wake detection and enable ACPI resume - #960
junkurera13 wants to merge 8 commits into
Conversation
bsp_setup_msr_save_state() is called unconditionally on the BSP's first pass through smm_relocation_handler() and reads MSR_SMM_FEATURE_CONTROL (0x4e0) whenever MSR_SMM_MCA_CAP (0x17d) reports SMM_CPU_SVRSTR. Emerald Rapids reports that bit, but Xeon-SP does not implement 0x4e0: SMM feature control lives in UBOX DFX PCI config space at offset 0x8c, see smihandler_soc_at_finalize(). The rdmsr #GPs in the relocation handler, which has no IDT, so the CPU wanders off and the watchdog resets the board a few seconds after "In relocation handler: CPU 0". Hardcode SMM_CPU_SVRSTR as unsupported so 0x4e0 is never touched, as done for Snowridge. All xeon_sp generations keep SMM feature control in UBOX PCI space, so this goes at the xeon_sp level; it is a no-op where the capability is absent. TEST=ASRock SPC741D8 with Emerald Rapids completes SMM relocation and boots to payload. Change-Id: Ic1cc95c4cf31e44fc29c9f859487c2dd47752d52 Signed-off-by: Michał Kopeć <michal.kopec@3mdeb.com> Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
QEMU's ACPI PM clears SLP_TYP on wake while leaving WAK_STS set, so the ICH9 SLP_TYP==S3 check never fires and the board cold-boots. Detect S3 from WAK_STS on Q35, advertise QEMU-compatible _S3/_S5 (SLP_TYP 1/0), and recover CBMEM so ramstage can jump to the FACS waking vector. Fixes: Dasharo/dasharo-issues#902 Co-authored-by: Isas2525 <Isas2525@users.noreply.github.com>
|
Thanks for taking a look when you can. This targets dasharo-issues#902 (bounty-easy / QEMU Q35 S3). pre-commit is green; the Dasharo Actions workflow is waiting on first-time contributor approval: Happy to address review feedback quickly. I can also add an OSFV-style regression once the firmware approach looks acceptable. |
Stock-firmware verification (this machine)Used published qemu-system-x86_64 -machine q35,smm=on -m 2G \
-drive if=pflash,format=raw,file=qemu_q35.rom \
-drive file=ubuntu-cloud.img,format=qcow2,if=none,id=disk0 \
-device ide-hd,drive=disk0,bus=ide.0 \
...Results on unpatched v0.2.1:
This matches #902: without QEMU-correct Next: rebuild with this PR’s qemu-q35 changes and re-check that |
HAVE_ACPI_RESUME plus SMM_TSEG selects TSEG_STAGE_CACHE, but qemu-q35 left SMM_RESERVED_SIZE at 0. Romstage then detected WAK_STS as S3 and postcar_cache_invalid() reset, which clears WAK_STS and looks like a cold boot. Reserve 2MiB at the top of an 8MiB TSEG, force DASHARO_PREFER_S3_SLEEP for EDK2 images, treat leftover QEMU SLP_TYP 1 as S3, log detect at BIOS_EMERG on stock loglevel-0 images, and add a firmware-only QEMU smoke script. Fixes: Dasharo/dasharo-issues#902 Co-authored-by: Isas2525 <Isas2525@users.noreply.github.com>
grep -q on a piped serial dump exits at the first match and SIGPIPEs the producer. With set -o pipefail that looks like a missed "S3 Resume" even when the firmware path succeeded. Search the QEMU serial file directly instead. Co-authored-by: Isas2525 <Isas2525@users.noreply.github.com>
Cold-boot "Payload not loaded" satisfied the post-wake wait, so QEMU could be killed before cached ramstage ran. Snapshot the serial offset at system_wakeup and require postcar "Jumping to image" in new bytes. Co-authored-by: Isas2525 <Isas2525@users.noreply.github.com>
QEMU publishes an ACPI 1.0 RSDP (XSDT=0) and FADT with x_firmware_ctl=0. Walking only XSDT / x_firmware_ctl printed "No FADT found" on S3 and never jumped to the OS waking vector. On QEMU, DCACHE_RAM is ordinary DRAM (q35: 0x10000-0xa0000). Zeroing that whole window in bootblock erased firmware_waking_vector on every S3 reset. Only clear allocated CAR objects through _car_unallocated_start. Print the first bytes at the waking vector before the trampoline jump. Co-authored-by: Isas2525 <Isas2525@users.noreply.github.com>
Add a tiny payload that programs FACS.firmware_waking_vector to a real-mode stub at 0x1000 (below qemu CAR) and prints Q35VEC on COM1 after the trampoline jump. s3-verify.sh injects it with cbfstool. Document the ACPI 1.0 FADT/RSDT path and CAR DRAM constraint in the qemu-q35 S3 test matrix. Co-authored-by: Isas2525 <Isas2525@users.noreply.github.com>
Record s3-verify.sh PASS output: cold s3resume=0, wake s3resume=1, RSDT/FACS lookup, and Q35VEC after the 0x1000 waking-vector jump. Co-authored-by: Isas2525 <Isas2525@users.noreply.github.com>
Update: firmware path verifiedPushed follow-up commits on this PR (
Root-cause addendum beyond the earlier WAK_STS note: bootblock was zeroing the entire CAR DRAM window on S3 reset, which erased a waking vector in that range. Fix zeros only allocated CAR and parks the smoke vector at Evidence file: Still requesting assignment on dasharo-issues#902 for the bounty-easy payout path, and happy to add an Ubuntu guest pass / OSFV test if maintainers want that before merge. |
Summary
Fixes S3 suspend/resume detection on the QEMU Q35 Dasharo path (dasharo-issues#902).
QEMU’s ACPI PM is not ICH9: S3 uses
SLP_TYP=1, S5 uses0, and on wake QEMU resetsPM1_CNTwhile settingPM1_STS.WAK_STS. coreboot’s generic resume detect requiredSLP_TYP == ACPI_S3(5), so romstage always took a cold boot aftersystem_wakeup.This change:
HAVE_ACPI_RESUMEfor qemu-q35_S3/_S5in the DSDTWAK_STS(real ICH9 path unchanged)poweroff()on Q35Closes: Dasharo/dasharo-issues#902 (partial — firmware path; needs guest verification)
Verification (still needed on a machine with QEMU + Ubuntu disk)
Guest:
systemctl suspend. Monitor:system_wakeup.Expected serial:
SB: Resume from S3 detected.thenS3 Resume/ OS waking vector — not onlyNormal boot.Limitations
FACS.firmware_waking_vectorcan still appear to cold-boot the payload after firmware detects S3AI disclosure
Implemented with Cursor cloud agent assistance. Design checked against QEMU ACPI PM behavior (
acpi_pm_cnt_write/acpi_notify_wakeup/acpi_pm1_cnt_reset) and coreboot’s existingHAVE_ACPI_RESUMEpath. A human QEMU + OS resume run is still required before treating this as fully validated.