Skip to content

emulation/qemu-q35: fix S3 wake detection and enable ACPI resume - #960

Open
junkurera13 wants to merge 8 commits into
Dasharo:dasharofrom
junkurera13:cursor/qemu-q35-s3-resume-9ae7
Open

junkurera13 wants to merge 8 commits into
Dasharo:dasharofrom
junkurera13:cursor/qemu-q35-s3-resume-9ae7

Conversation

@junkurera13

Copy link
Copy Markdown

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 uses 0, and on wake QEMU resets PM1_CNT while setting PM1_STS.WAK_STS. coreboot’s generic resume detect required SLP_TYP == ACPI_S3 (5), so romstage always took a cold boot after system_wakeup.

This change:

  • Enables HAVE_ACPI_RESUME for qemu-q35
  • Advertises QEMU-correct _S3 / _S5 in the DSDT
  • Detects Q35 resume via WAK_STS (real ICH9 path unchanged)
  • Wires romstage CBMEM / handoff for the ramstage waking-vector jump
  • Uses QEMU S5 encoding in poweroff() on Q35

Closes: Dasharo/dasharo-issues#902 (partial — firmware path; needs guest verification)

Verification (still needed on a machine with QEMU + Ubuntu disk)

cp configs/config.emulation_qemu_x86_q35_uefi .config
make olddefconfig && make
# confirm CONFIG_HAVE_ACPI_RESUME=y

qemu-system-x86_64 -M q35 -m 2G -bios build/coreboot.rom \
  -serial stdio -monitor telnet:127.0.0.1:4444,server,nowait \
  -hda <ubuntu-disk>

Guest: systemctl suspend. Monitor: system_wakeup.

Expected serial: SB: Resume from S3 detected. then S3 Resume / OS waking vector — not only Normal boot.

Limitations

  • Not run end-to-end with an Ubuntu guest in the build environment used for this PR
  • Guests that never program FACS.firmware_waking_vector can still appear to cold-boot the payload after firmware detects S3
  • No OSFV regression test included yet

AI 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 existing HAVE_ACPI_RESUME path. A human QEMU + OS resume run is still required before treating this as fully validated.

mkopec and others added 2 commits August 31, 2026 10:53
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>
@junkurera13

Copy link
Copy Markdown
Author

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:
https://github.com/Dasharo/coreboot/actions/runs/34181387416

Happy to address review feedback quickly. I can also add an OSFV-style regression once the firmware approach looks acceptable.

@junkurera13

Copy link
Copy Markdown
Author

Stock-firmware verification (this machine)

Used published qemu_q35_v0.2.1 ROM with:

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:

  • Guest boots Ubuntu 22.04 on serial.
  • /sys/power/state is missing (No such file or directory) — ACPI sleep is not offered to the OS.
  • system_wakeup from the QEMU monitor returns: Error: Unable to wake up: guest is not in suspended state.

This matches #902: without QEMU-correct _S3 / resume support, the platform cannot enter a real S3 path from the guest.

Next: rebuild with this PR’s qemu-q35 changes and re-check that /sys/power/state includes mem, then suspend + system_wakeup.

cursoragent and others added 6 commits September 8, 2026 03:18
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>
@junkurera13

Copy link
Copy Markdown
Author

Update: firmware path verified

Pushed follow-up commits on this PR (+796/−26, 15 files). s3-verify.sh PASS on QEMU 8.2.2:

  • cold boot: s3resume=0
  • after suspend/system_wakeup: s3resume=1, S3 Resume, FACS found, jump to waking vector, payload prints Q35VEC

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 0x1000.

Evidence file: Documentation/mainboard/emulation/qemu-q35-s3-verify.txt.

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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

S3 support in Q35

3 participants