Skip to content

feat: implement virtio based host-guest communication - #1717

Closed
andreiltd wants to merge 19 commits into
hyperlight-dev:virtq-foundationsfrom
andreiltd:virtq-takeover
Closed

feat: implement virtio based host-guest communication#1717
andreiltd wants to merge 19 commits into
hyperlight-dev:virtq-foundationsfrom
andreiltd:virtq-takeover

Conversation

@andreiltd

Copy link
Copy Markdown
Member

See rendered design doc. For broader context see HIP PR: #1112

This patch replaces stack based communication with function calls transported over virtual queues. The documentation covers two current limitations: snapshots do not support retained buffers, and the host owns the transport arena. Addressing both is deferred to future work.

Copilot AI lite review requested due to automatic review settings August 11, 2026 17:16

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.

Copilot wasn't able to review this pull request because it exceeds the maximum number of lines (20,000). Try reducing the number of changed lines and requesting a review from Copilot again.

@andreiltd andreiltd added kind/enhancement For PRs adding features, improving functionality, docs, tests, etc. regen-goldens Regenerate snapshot golden fixtures ready-for-review PR is ready for (re-)review labels Aug 11, 2026
@jsturtevant

Copy link
Copy Markdown
Contributor

The documentation covers two current limitations: snapshots do not support retained buffers, and the host owns the transport arena. Addressing both is deferred to future work.

What are the implications? Is there any behavior changes for existing hyperlight consumers?

@andreiltd

andreiltd commented Aug 12, 2026

Copy link
Copy Markdown
Member Author

The documentation covers two current limitations: snapshots do not support retained buffers, and the host owns the transport arena. Addressing both is deferred to future work.

What are the implications? Is there any behavior changes for existing hyperlight consumers?

There is no behavior changes for existing consumers, there is a new parameter type that is zero-copy: ByteChunks. VecBytes  still copies into guest heap memory, so retained values survive snapshots. The limitation applies only to this new type.

Adding snapshot support for retained  ByteChunks  is relatively straightforward. Buffer allocation state lives entirely in the guest, so the guest must publish a manifest listing the addresses the host should capture. The current implementation only detects outstanding  ByteChunks  borrows and returns an error if any exist. That said, the PR is already enormous so I decided to not implement it for this mvp.

The only real change for existing customers is minimum scratch and guest heap size increase as they need to account for virtual queues bookkeeping.

@ludfjig ludfjig 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.

I haven't looked very detailed through the code yet:

You mentioned offline that separating ByteChunks into a separate PR without the virtio stuff is hard because ByteChunks dependo on virtio. Would it be possible instead to have the first pr be virtio stuff, and second be the bytechunks (just to make it easier to review)?

It's also my understanding that the new parameter type vec<Bytes> (rather than just Bytes without vec) is necessary for the guest to receive data zerocopy as it's not contiguous memory, but this type is also mirrored in the host api. I guess my question is do we expect it to be a useful for a host to provide multiple Bytes rather than just 1 contiguous one?

It looks like hlbytechunks and hlsizeprefixedbytechunks are not used anymore after recent commits, should they be removed?

Comment thread src/hyperlight_host/src/mem/layout.rs Outdated
Comment on lines 334 to 364
pub(crate) fn is_compatible_with(&self, other: &Self) -> bool {
// Exhaustive destructure so adding a field to
// `SandboxMemoryLayout` fails to compile here, forcing the
// author to decide whether it participates in compatibility.
let Self {
input_data_size,
output_data_size,
heap_size,
code_size,
init_data_size,
init_data_permissions,
scratch_size,
g2h_queue_size,
h2g_queue_size,
g2h_buffer_size,
h2g_buffer_size,
g2h_pool_pages,
h2g_pool_pages,
snapshot_size: _,
pt_size: _,
} = self;
*input_data_size == other.input_data_size
&& *output_data_size == other.output_data_size
&& *heap_size == other.heap_size
*heap_size == other.heap_size
&& *code_size == other.code_size
&& *init_data_size == other.init_data_size
&& *init_data_permissions == other.init_data_permissions
&& *scratch_size == other.scratch_size
&& *g2h_queue_size == other.g2h_queue_size
&& *h2g_queue_size == other.h2g_queue_size
&& *g2h_buffer_size == other.g2h_buffer_size
&& *h2g_buffer_size == other.h2g_buffer_size
&& *g2h_pool_pages == other.g2h_pool_pages
&& *h2g_pool_pages == other.h2g_pool_pages
}

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.

just fyi I have a draft PR #1728 that will relax this requiement, and use the target snapshot as authority, requiring nothing from the sandbox's layout

@andreiltd

Copy link
Copy Markdown
Member Author

Would it be possible instead to have the first pr be virtio stuff, and second be the bytechunks (just to make it easier to review)?

Possibly, but I think it would make more sense to do the other way around and maybe accept some temporary stubs for virtio. I would have to have a closer look. I understand this is quite a lot to chew, so maybe it's worth to go through additional effort to split this.

I guess my question is do we expect it to be a useful for a host to provide multiple Bytes rather than just 1 contiguous one?

Bytes would work, yes. although I think it is pretty common to collect Bytes and send it as chunks. For example hyper code (without streams) to read body till EOF could look something like this:

let mut chunks: Vec<Bytes> = Vec::new();

println!("reading request body chunks");
while let Some(next) = req.body_mut().data().await {
    let Ok(chunk) = next else {
        panic!()     
    };
    chunks.push(chunk);
}

It would be slightly annoying to require to make it contiguous before transport. To be fair I think there is also a bit surprising fact about this API, that there is no guarantee that chunking as presented on the sender side will survive transport with the same boundaries.

It looks like hlbytechunks and hlsizeprefixedbytechunks are not used anymore after recent commits, should they be removed?

Sure!

@andreiltd

Copy link
Copy Markdown
Member Author

For visibility, here is the wip branch that changes the ownership of pools from host owned to guest owned, that could potentially land together with the changes in this PR:

andreiltd@18824d4

@syntactically

syntactically commented Aug 20, 2026

Copy link
Copy Markdown
Member

I understand this is quite a lot to chew, so maybe it's worth to go through additional effort to split this.

If it's not too much effort, I think it would be useful to consider.

It would be slightly annoying to require to make it contiguous before transport

I agree; I think it's important that this support multiple input slices to get the ability to build single-copy higher-level parameter serialisation on it. (See page 5 of my serialisation design doc)

Bytes

For the host->guest direction, is there a reason to prefer bytes::Bytes to &[u8]? I think since we copy into the guest memory during the call procedure, any accesses should be nicely scoped?

Initialize queues before first guest entry. Carry host calls, logs,
external values, and bounded responses over G2H chains.

Signed-off-by: Tomasz Andrzejak <andreiltd@gmail.com>
Signed-off-by: Tomasz Andrzejak <andreiltd@gmail.com>
Route guest calls, host calls, results, and logs through bidirectional
packed virtqueues. Stream dense messages across exact chain batches and
reserve H2G capacity for retained external values.

Keep external byte returns typed through guest dispatch and support
owner-backed byte chunks in Rust and C guests.

Store canonical rings in a versioned OCI transport layer and validate
them during snapshot load and restore.

Signed-off-by: Tomasz Andrzejak <andreiltd@gmail.com>
Signed-off-by: Tomasz Andrzejak <andreiltd@gmail.com>
Signed-off-by: Tomasz Andrzejak <andreiltd@gmail.com>
Enter the guest once before capture to canonicalize both queues.

Signed-off-by: Tomasz Andrzejak <andreiltd@gmail.com>
Report retained pool slots through the checkpoint mailbox. Keep rejected
sandboxes usable for release and retry.

Signed-off-by: Tomasz Andrzejak <andreiltd@gmail.com>
Signed-off-by: Tomasz Andrzejak <andreiltd@gmail.com>
Signed-off-by: Tomasz Andrzejak <andreiltd@gmail.com>
Signed-off-by: Tomasz Andrzejak <andreiltd@gmail.com>
Signed-off-by: Tomasz Andrzejak <andreiltd@gmail.com>
Signed-off-by: Tomasz Andrzejak <andreiltd@gmail.com>
Signed-off-by: Tomasz Andrzejak <andreiltd@gmail.com>
Signed-off-by: Tomasz Andrzejak <andreiltd@gmail.com>
Signed-off-by: Tomasz Andrzejak <andreiltd@gmail.com>
This still will cause OOM as the test requires but will increase initial
heap size so that virtqueus finish initialization.

Signed-off-by: Tomasz Andrzejak <andreiltd@gmail.com>
Signed-off-by: Tomasz Andrzejak <andreiltd@gmail.com>
Signed-off-by: Tomasz Andrzejak <andreiltd@gmail.com>
Signed-off-by: Tomasz Andrzejak <andreiltd@gmail.com>
@andreiltd
andreiltd changed the base branch from main to virtq-foundations September 3, 2026 13:09
@andreiltd
andreiltd marked this pull request as draft September 3, 2026 13:16
@github-actions github-actions Bot removed the ready-for-review PR is ready for (re-)review label Sep 3, 2026
@andreiltd andreiltd closed this Sep 3, 2026
@andreiltd

Copy link
Copy Markdown
Member Author

I will close this one in favor of stacked PR: #1794. This PR cannot be reused in the stack because the base commit live in forks, which apparently is not supported in stacked PRs.

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

Labels

kind/enhancement For PRs adding features, improving functionality, docs, tests, etc. regen-goldens Regenerate snapshot golden fixtures

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants