Skip to content

openhcl: write hibernate token to VMGS on power transitions - #4235

Merged
Mike Ebersol (mebersol) merged 7 commits into
microsoft:mainfrom
mebersol:user/mebersol/openhcl-hibernate-token
Aug 14, 2026
Merged

openhcl: write hibernate token to VMGS on power transitions#4235
Mike Ebersol (mebersol) merged 7 commits into
microsoft:mainfrom
mebersol:user/mebersol/openhcl-hibernate-token

Conversation

@mebersol

Copy link
Copy Markdown
Collaborator

Summary

Adds a self-contained OpenHCL hibernate module that manages an 8-byte "hibernate token" stored in the VMGS HIBERNATION_TOKEN file, mirroring the legacy HCL HclPowerServices / DevicePlatform::WriteUefiConfigBlob behavior. This is the first of two PRs split out from the larger hibernation-firmware work; it covers only the token lifecycle (writing, clearing, telemetry, and servicing persistence). Firmware-image snapshot/restore is a follow-up.

Motivation

Hibernation-enabled guests need a durable marker recording their power state and the firmware version they hibernated under, so the paravisor can detect resume-vs-cold-boot and (in a later change) enforce firmware-version consistency across a hibernate/resume cycle.

Testing

  • Unit tests in hibernate.rs cover the token round-trip against an in-memory VMGS: absent read, write→read→delete, the NONE value, and a corrupt (non-8-byte) token.

Note: underhill_core is #![cfg(target_os = "linux")], so it compiles and tests only on a Linux build (CI / WSL). vmgs_format, vmgs_broker, and formatting were validated locally.

Adds an OpenHCL hibernate module that reads/writes/deletes an 8-byte version-encoded token in VMGS FileId::HIBERNATION_TOKEN, mirroring legacy HCL HclPowerServices. Writes the current firmware token on hibernate, NONE on power off/reset, logs telemetry and consumes any prior token at boot, and carries the token across servicing via HibernateSavedState. Adds vmgs_broker delete_file plumbing and unit tests for the token round-trip.
Copilot AI lite review requested due to automatic review settings August 13, 2026 18:47
@mebersol
Mike Ebersol (mebersol) requested a review from a team as a code owner August 13, 2026 18:47
@mebersol Mike Ebersol (mebersol) added the backport_1.8.2607 Change should be backported to the release/1.8.2607 branch label Aug 13, 2026

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR introduces OpenHCL-side management of a durable 8-byte “hibernate token” stored in VMGS (file ID 14), wiring it into Underhill boot/restore and halt/power-transition flows so the token can be read/consumed at boot and persisted on hibernate/power-off/reset.

Changes:

  • Rename VMGS file ID 14 to HIBERNATION_TOKEN and update tooling to reference it.
  • Add VMGS broker support for deleting a file (DeleteFile) and expose it via VmgsClient.
  • Add a new underhill_core::hibernate module plus servicing-state plumbing and halt-task integration to write/clear the token on power transitions.

Reviewed changes

Copilot reviewed 10 out of 11 changed files in this pull request and generated 4 comments.

Show a summary per file
File Description
vm/vmgs/vmgstool/src/main.rs Updates CLI file-id name mapping to include HIBERNATION_TOKEN.
vm/vmgs/vmgs_format/src/lib.rs Renames VMGS fixed file ID 14 to HIBERNATION_TOKEN.
vm/vmgs/vmgs_broker/src/client.rs Adds VmgsClient::delete_file RPC wrapper (instrumented).
vm/vmgs/vmgs_broker/src/broker.rs Adds VmgsBrokerRpc::DeleteFile and dispatch handling.
openhcl/underhill_core/src/worker.rs Reads/consumes token at boot; writes token on halt transitions.
openhcl/underhill_core/src/servicing.rs Adds servicing saved-state field for pinned hibernate token.
openhcl/underhill_core/src/lib.rs Wires in the new hibernate module.
openhcl/underhill_core/src/hibernate.rs New module implementing read/write/delete token helpers + unit tests.
openhcl/underhill_core/src/dispatch/mod.rs Persists hibernate_token into servicing saved state.
openhcl/underhill_core/Cargo.toml Adds disklayer_ram dev-dependency for VMGS in-memory tests.
Cargo.lock Updates lockfile for the new dev-dependency usage.

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread vm/vmgs/vmgs_broker/src/client.rs
Comment thread vm/vmgs/vmgstool/src/main.rs
Comment thread openhcl/underhill_core/src/hibernate.rs Outdated
Comment thread openhcl/underhill_core/src/worker.rs Outdated
Copilot AI review requested due to automatic review settings August 13, 2026 19:10

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 11 out of 12 changed files in this pull request and generated no new comments.

Suppressed comments (2)

openhcl/underhill_core/src/hibernate.rs:97

  • read_token() treats any buffer with at least 8 bytes as a valid token via first_chunk::<8>(), but the token is expected to be exactly 8 bytes (and the tests/docs describe non-8-byte tokens as corrupt). If the VMGS file is corrupted to a larger size, this will silently parse the first 8 bytes instead of flagging corruption.
        Ok(buf) => match buf.first_chunk::<8>() {

vm/vmgs/vmgs_broker/src/broker.rs:18

  • VmgsBrokerError::FileInfoNotAllocated is now used by both reads and deletes, but the error text still says "being read", which can be misleading when surfaced from DeleteFile. Consider making the message operation-agnostic.
    #[error("no allocated bytes for file id being read")]

Copilot AI review requested due to automatic review settings August 13, 2026 19:20

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 11 out of 12 changed files in this pull request and generated no new comments.

Suppressed comments (2)

vm/vmgs/vmgs_broker/src/broker.rs:19

  • VmgsBrokerError::FileInfoNotAllocated is now used for operations beyond reads (e.g. DeleteFile), but its error message still says "for file id being read", which is misleading when surfaced to callers/logs. Make the message operation-neutral.
    /// The requested file has no allocated bytes (i.e. does not exist).
    #[error("no allocated bytes for file id being read")]
    FileInfoNotAllocated,

openhcl/underhill_core/src/hibernate.rs:97

  • read_token() treats any buffer with length >= 8 as valid because first_chunk::<8>() only checks the minimum length. This contradicts the intent (and test comment) that tokens must be exactly 8 bytes, and would silently accept/ignore trailing bytes. Validate buf.len() == 8 before decoding.
    match vmgs_client.read_file(vmgs::FileId::HIBERNATION_TOKEN).await {
        Ok(buf) => match buf.first_chunk::<8>() {
            Some(bytes) => {
                let token = u64::from_le_bytes(*bytes);
                tracing::info!(

Comment thread openhcl/underhill_core/src/hibernate.rs
Comment thread openhcl/underhill_core/src/hibernate.rs
Copilot AI review requested due to automatic review settings August 13, 2026 19:57

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 11 out of 12 changed files in this pull request and generated no new comments.

Suppressed comments (4)

openhcl/underhill_core/src/worker.rs:4039

  • Same as PowerOff: awaiting the VMGS write here can delay (or block) the reset request to the host if VMGS I/O stalls. Bound this best-effort write with a timeout so resets still proceed.
                    if let Some(hibernate_halt) = &hibernate_halt {
                        hibernate::write_token(&hibernate_halt.vmgs_client, hibernate::token::NONE)
                            .await;
                    }

openhcl/underhill_core/src/worker.rs:4050

  • Awaiting the VMGS token write here means a stalled VMGS broker/storage can indefinitely delay the hibernate request to the host. If this write is intended to be best-effort, consider bounding it with a timeout and proceeding even if it expires.
                    if let Some(hibernate_halt) = &hibernate_halt {
                        hibernate::write_token(
                            &hibernate_halt.vmgs_client,
                            hibernate_halt.current_token,
                        )
                        .await;
                    }

vm/vmgs/vmgs_broker/src/broker.rs:18

  • The FileInfoNotAllocated error is now used for operations other than reads (e.g. DeleteFile), but the error text still says "being read", which makes logs/telemetry misleading. Consider making the message operation-agnostic.
    /// The requested file has no allocated bytes (i.e. does not exist).
    #[error("no allocated bytes for file id being read")]
    FileInfoNotAllocated,

openhcl/underhill_core/src/worker.rs:4030

  • This halt path awaits a VMGS write before notifying the host. If the VMGS broker or underlying storage stalls, this can delay (or block) the power-off transition indefinitely, contradicting the "never block" intent. Consider bounding the wait with a CancelContext timeout and proceeding even if it expires.

This issue also appears in the following locations of the same file:

  • line 4036
  • line 4044
                    if let Some(hibernate_halt) = &hibernate_halt {
                        hibernate::write_token(&hibernate_halt.vmgs_client, hibernate::token::NONE)
                            .await;
                    }

Comment thread openhcl/underhill_core/src/worker.rs
@github-actions

Copy link
Copy Markdown

Comment thread openhcl/underhill_core/src/hibernate.rs Outdated
Comment thread openhcl/underhill_core/src/hibernate.rs Outdated
Comment thread openhcl/underhill_core/src/worker.rs Outdated
Add an Other(u64) variant so any on-disk value round-trips through the type without truncation, and add unit tests covering the full u64 range.
Copilot AI review requested due to automatic review settings August 13, 2026 22:19

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 11 out of 12 changed files in this pull request and generated no new comments.

Suppressed comments (3)

openhcl/underhill_core/src/hibernate.rs:101

  • Similarly, delete_token() is awaited by its callers, so it can delay boot/power transitions if VMGS I/O stalls. The doc comment currently implies it can’t block; consider rewording to "errors are logged/ignored" (or add a timeout if that’s the intended behavior).
/// Best-effort deletion of the hibernate token, clearing any prior hibernate
/// marker. Never blocks the power transition.

openhcl/underhill_core/src/hibernate.rs:82

  • This doc comment says failures "never block the power transition", but write_token() is awaited (e.g., in halt_task) and can therefore delay the transition if VMGS I/O stalls. Consider rewording to the precise guarantee (errors are logged/ignored) or add an explicit timeout if non-blocking latency is required.

This issue also appears on line 100 of the same file.

/// Best-effort write of an 8-byte hibernate token to the VMGS. Failures are
/// logged but never block the power transition.

vm/vmgs/vmgs_broker/src/broker.rs:19

  • The FileInfoNotAllocated error message says "being read", but this error is now also returned from DeleteFile (and potentially other operations). The message should be operation-agnostic so logs and surfaced errors aren’t misleading.
    /// The requested file has no allocated bytes (i.e. does not exist).
    #[error("no allocated bytes for file id being read")]
    FileInfoNotAllocated,

The no-VMGS boot branch silently returned None; log a warning so the missing token-persistence path is diagnosable.
Copilot AI review requested due to automatic review settings August 13, 2026 22:31

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 11 out of 12 changed files in this pull request and generated no new comments.

Suppressed comments (1)

vm/vmgs/vmgs_broker/src/broker.rs:19

  • VmgsBrokerError::FileInfoNotAllocated is now used for non-read operations (e.g. DeleteFile), but the error text still says "being read", which can be misleading in logs and when surfaced through VmgsClientError::Vmgs.
pub enum VmgsBrokerError {
    /// The requested file has no allocated bytes (i.e. does not exist).
    #[error("no allocated bytes for file id being read")]
    FileInfoNotAllocated,

@github-actions

Copy link
Copy Markdown

}

impl Token {
/// Written when the current firmware hibernates; bump per release.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should note this in the internal guide page on what to do for new release branches, otherwise we're going to forget it.

@mebersol
Mike Ebersol (mebersol) merged commit 3764203 into microsoft:main Aug 14, 2026
101 of 104 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

backport_1.8.2607 Change should be backported to the release/1.8.2607 branch

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants