Skip to content

feat(aarch64): support external graceful shutdown via SendCtrlAltDel#5984

Open
14sea wants to merge 1 commit into
firecracker-microvm:mainfrom
14sea:fix/aarch64-pl061-shutdown
Open

feat(aarch64): support external graceful shutdown via SendCtrlAltDel#5984
14sea wants to merge 1 commit into
firecracker-microvm:mainfrom
14sea:fix/aarch64-pl061-shutdown

Conversation

@14sea

@14sea 14sea commented Jun 19, 2026

Copy link
Copy Markdown

Changes

Add external graceful shutdown support on aarch64 by reusing the existing
SendCtrlAltDel action.

  • Expose a minimal PL061 GPIO controller as an aarch64 MMIO device and
    describe a gpio-keys power button (KEY_POWER) in the FDT.
  • Reuse SendCtrlAltDel: on x86_64 it still injects CTRL+ALT+DEL through the
    i8042 device (unchanged); on aarch64 it drives a short, synchronous
    press/release pulse on the virtual power button. The API no longer rejects the
    action with a 400 on aarch64.
  • The PL061 SPI is declared edge-triggered to match Firecracker's plain
    irqfd injection (no resample fd). A level-high line would never be de-asserted
    and the GIC would re-fire it after the guest EOIs, storming the host.
  • Save/restore the PL061 register state across snapshots so the button keeps
    working on a restored microVM. The snapshot version is bumped 10.0.0
    11.0.0.
  • Add the guest-kernel options the gpio-keys path needs
    (CONFIG_GPIOLIB, CONFIG_GPIO_PL061, CONFIG_INPUT_KEYBOARD,
    CONFIG_KEYBOARD_GPIO) to resources/guest_configs/ci.config, and update
    docs/api_requests/actions.md, docs/device-api.md and CHANGELOG.md.

This follows the direction confirmed by @ShadowCurse in
#2046:
no feature gating (always enabled on aarch64), reuse SendCtrlAltDel, and rely
on the systemd-logind already present in the CI rootfs.

A couple of points worth a maintainer's eye:

  • Kernel config placement. I put the gpio-keys options in ci.config rather
    than a separate debug.config-style fragment, because the integration tests
    boot the non-debug CI kernels (which only concatenate ci.config), and the
    file already carries the x86 "CTRL+ALT+DEL support" section. Happy to move it
    if you'd prefer a dedicated fragment.
  • test_send_ctrl_alt_del on aarch64. It is kept skipif-skipped on aarch64
    for now: the kernel config is included here, but a fresh PR runs against the
    currently-published guest-kernel artifacts, which do not yet have gpio-keys.
    Once the CI guest kernels are rebuilt with this ci.config change the skip can
    be removed so the existing test exercises the aarch64 path. Would you like me
    to drop the skip in this PR, or as a follow-up after the artifacts are
    rebuilt?

Hardware validation

Validated on real aarch64 + KVM hardware (RK3568, Ubuntu guest), on this exact
rebased commit:

  • No interrupt storm: /proc/interrupts shows the line as Edge; the count
    increments by exactly +2 per action (press + release) and host CPU stays
    effectively idle (~0.7% over the window). A level storm would peg a CPU.
  • Graceful poweroff: with systemd-logind active, SendCtrlAltDel
    systemd-poweroffreboot: Power downKVM_SYSTEM_EVENT
    Firecracker exiting successfully. exit_code=0.
  • Snapshot/restore: after a full snapshot → restore cycle, the restored guest
    still takes the interrupt (+2) and emits a byte-identical KEY_POWER
    press/release event stream on /dev/input/event0, confirming the PL061
    interrupt-enable state survives restore.

Reason

Closes #2046. aarch64 previously rejected SendCtrlAltDel with a 400 and had no
mechanism to request a graceful shutdown of a microVM from the host, unlike
x86_64. This brings aarch64 to parity using the standard guest gpio-keys path.

License Acceptance

By submitting this pull request, I confirm that my contribution is made under
the terms of the Apache 2.0 license. For more information on following Developer
Certificate of Origin and signing off your commits, please check
CONTRIBUTING.md.

PR Checklist

  • I have read and understand CONTRIBUTING.md.
  • I have verified the PR builds and passes clippy -D warnings on both
    x86_64 and aarch64 (tools/devtool build on aarch64 hardware); CI runs the
    full checkbuild --all.
  • I have run tools/devtool checkstyle to verify that the PR passes the
    automated style checks.
  • I have described what is done in these changes, why they are needed, and
    how they are solving the problem in a clear and encompassing way.
  • I have updated any relevant documentation (both in code and in the docs)
    in the PR.
  • I have mentioned all user-facing changes in CHANGELOG.md.
  • If a specific issue led to this PR, this PR closes the issue.
  • When making API changes, I have followed the
    Runbook for Firecracker API changes.
  • I have tested all new and changed functionalities in unit tests and/or
    integration tests (PL061 device unit tests added; the test_send_ctrl_alt_del
    integration test remains aarch64-skipped pending a gpio-keys CI kernel — see
    above).
  • I have linked an issue to every new TODO.

  • This functionality cannot be added in rust-vmm.

Until now `SendCtrlAltDel` was rejected with a 400 on aarch64 and there was
no way to request a graceful shutdown of a microVM from the host. Fixes firecracker-microvm#2046.

Add a minimal PL061 GPIO controller as an aarch64 MMIO device and describe a
`gpio-keys` power button (KEY_POWER) in the FDT. `SendCtrlAltDel` is reused: on
x86_64 it still injects CTRL+ALT+DEL through the i8042 device; on aarch64 it
drives a short press/release pulse on the virtual power button. A guest with the
standard gpio-keys driver and a power-key consumer (e.g. systemd-logind, which
defaults to HandlePowerKey=poweroff) then shuts down cleanly and Firecracker
exits on the resulting KVM_SYSTEM_EVENT_SHUTDOWN.

Details:
- The PL061 SPI is declared edge-triggered to match Firecracker's plain irqfd
  injection (no resample fd). A level-high line would never be de-asserted and
  the GIC would re-fire it after the guest EOIs, storming the host.
- The PL061 register state is saved and restored across snapshots, so the power
  button keeps working on a restored microVM. The snapshot version is bumped to
  11.0.0 accordingly.
- The press/release pulse runs synchronously so the two edges stay atomic with
  respect to other API actions; a concurrent snapshot can never capture the
  button half-pressed.

Validated on aarch64 + KVM hardware: KEY_POWER is delivered to the guest with no
interrupt storm, systemd-logind powers the VM off automatically, and the path
also works after a snapshot/restore cycle.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Signed-off-by: 14sea <wanhuaning@gmail.com>
@JackThomson2 JackThomson2 requested a review from ShadowCurse June 24, 2026 14:07
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.

AArch64: graceful power-off from external

1 participant