Skip to content

wip: runtime-rs: Implement PoC for OpenVMM#438

Draft
sprt wants to merge 33 commits intomsft-previewfrom
sprt/openvmm
Draft

wip: runtime-rs: Implement PoC for OpenVMM#438
sprt wants to merge 33 commits intomsft-previewfrom
sprt/openvmm

Conversation

@sprt
Copy link
Copy Markdown

@sprt sprt commented Mar 26, 2026

No description provided.

sprt added 21 commits March 23, 2026 16:41
This avoids issues like below which are now errors in Rust 1.94:

error: a method with this name may be added to the standard library in the future
   --> src/libs/kata-sys-util/src/mount.rs:265:12
    |
265 |     if src.is_empty() {
    |            ^^^^^^^^
    |
    = warning: once this associated item is added to the standard library, the ambiguity may cause an error or change in behavior!
    = note: for more information, see issue #48919 <rust-lang/rust#48919>
    = help: call with fully qualified syntax `nix::NixPath::is_empty(...)` to keep using the current method

Signed-off-by: Aurélien Bombo <abombo@microsoft.com>
This avoids issues like below which are now errors in Rust 1.94.

error: unnecessary `unsafe` block
   --> src/libs/kata-sys-util/src/protection.rs:129:19
    |
129 |         let fn0 = unsafe { x86_64::__cpuid(0) };
    |                   ^^^^^^ unnecessary `unsafe` block
    |
    = note: `-D unused-unsafe` implied by `-D warnings`
    = help: to override `-D warnings` add `#[allow(unused_unsafe)]`

Signed-off-by: Aurélien Bombo <abombo@microsoft.com>
Seems like these are now errors in 1.94:

error: called `unwrap` on `self.0.right` after checking its variant with `is_some`
   --> src/dragonball/dbs_allocator/src/interval_tree.rs:306:13
    |
304 |         } else if key.min > self.0.key.max && self.0.right.is_some() {
    |                                               ---------------------- the check is happening here
305 |             // Safe to unwrap() because we have just checked it.
306 |             self.0.right.as_ref().unwrap().search_superset(key)
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
    = help: try using `match`
    = help: for further information visit https://rust-lang.github.io/rust-clippy/rust-1.94.0/index.html#unnecessary_unwrap
    = note: `-D clippy::unnecessary-unwrap` implied by `-D warnings`
    = help: to override `-D warnings` add `#[allow(clippy::unnecessary_unwrap)]`

error: called `unwrap` on `self.0.right` after checking its variant with `is_some`
   --> src/dragonball/dbs_allocator/src/interval_tree.rs:321:13
    |
319 |         } else if key.min > self.0.key.max && self.0.right.is_some() {
    |                                               ---------------------- the check is happening here
320 |             // Safe to unwrap() because we have just checked it.
321 |             self.0.right.as_mut().unwrap().search_superset_mut(key)
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
    = help: try using `match`
    = help: for further information visit https://rust-lang.github.io/rust-clippy/rust-1.94.0/index.html#unnecessary_unwrap

error: called `unwrap` on `self.0.left` after checking its variant with `is_some`
   --> src/dragonball/dbs_allocator/src/interval_tree.rs:518:13
    |
517 |         let mut candidate = if self.0.left.is_some() {
    |                             ------------------------ help: try: `if let Some(<item>) = &self.0.left`
518 |             self.0.left.as_ref().unwrap().first_match(constraint)
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
    = help: for further information visit https://rust-lang.github.io/rust-clippy/rust-1.94.0/index.html#unnecessary_unwrap

error: called `unwrap` on `self.0.right` after checking its variant with `is_some`
   --> src/dragonball/dbs_allocator/src/interval_tree.rs:527:25
    |
526 |         if candidate.is_none() && self.0.right.is_some() {
    |                                   ---------------------- the check is happening here
527 |             candidate = self.0.right.as_ref().unwrap().first_match(constraint);
    |                         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
    = help: try using `match`
    = help: for further information visit https://rust-lang.github.io/rust-clippy/rust-1.94.0/index.html#unnecessary_unwrap

Signed-off-by: Aurélien Bombo <abombo@microsoft.com>
This is the version used by OpenVMM.

Signed-off-by: Aurélien Bombo <abombo@microsoft.com>
Not functional yet but able to compile OpenVMM in proc.

Signed-off-by: Aurélien Bombo <abombo@microsoft.com>
Signed-off-by: Aurélien Bombo <abombo@microsoft.com>
Signed-off-by: Aurélien Bombo <abombo@microsoft.com>
`cargo check` was introduced in 3f1533a to check that Cargo.lock is in sync
with Cargo.toml. However, if there are uncommitted changes in the working
tree, the current invocation will immediately fail because of the `git
diff` call, which is frustrating for local development.

As it turns out, `cargo clippy` is a superset of `cargo check`, so we can
simply pass `--locked` to `cargo clippy` to detect Cargo.lock issues.

This is tested with the following change:

diff --git a/src/agent/Cargo.lock b/src/agent/Cargo.lock
index 96b6c67..e1963af 100644
--- a/src/agent/Cargo.lock
+++ b/src/agent/Cargo.lock
@@ -4305,6 +4305,7 @@ checksum = "8f50febec83f5ee1df3015341d8bd429f2d1cc62bcba7ea2076759d315084683"
 name = "test-utils"
 version = "0.1.0"
 dependencies = [
- "libc",
  "nix 0.26.4",
 ]

which results in the following output:

$ make -C src/agent check
make: Entering directory '/kata-containers/src/agent'
standard rust check...
cargo fmt -- --check
cargo clippy --all-targets --all-features --release --locked \
        -- \
        -D warnings
error: the lock file /kata-containers/src/agent/Cargo.lock needs to be updated but --locked was passed to prevent this
If you want to try to generate the lock file without accessing the network, remove the --locked flag and use --offline instead.
make: *** [../../utils.mk:184: standard_rust_check] Error 101
make: Leaving directory '/kata-containers/src/agent'

Signed-off-by: Aurélien Bombo <abombo@microsoft.com>
Add configuration-openvmm.toml.in template for the OpenVMM hypervisor
backend, modeled after the Dragonball configuration. Key settings:
- Uses inline-virtio-fs (built-in, no external virtiofsd)
- Uses virtio-blk-pci for rootfs block device
- Uses tcfilter networking model
- kernel_params include cgroup_no_v1=all for cgroup v2

Wire the template into the Makefile gated by USE_OPENVMM, following
the same pattern as USE_BUILDIN_DB for Dragonball. The generated
config file is placed at config/configuration-openvmm.toml.

Signed-off-by: Aurélien Bombo <abombo@microsoft.com>
Add the full set of OpenVMM crate dependencies needed for in-process
VM creation: openvmm_core, openvmm_defs, openvmm_resources,
openvmm_helpers, vm_manifest_builder, mesh/mesh_worker, pal_async,
and device resource crates (storvsp, scsidisk, netvsp, virtio, etc.).

All deps are optional and gated behind the 'openvmm' feature flag.

Note: dragonball and openvmm features cannot be enabled simultaneously
due to kvm-ioctls version conflicts (dragonball uses 0.12, openvmm
pulls in 0.14 transitively). When USE_OPENVMM=true, dragonball is
excluded from the feature set.

Signed-off-by: Aurélien Bombo <abombo@microsoft.com>
Add vmm_instance.rs wrapping OpenVMM's mesh_worker WorkerHandle for
in-process VM lifecycle control (launch, resume, pause, stop).

Update inner.rs to use VmmInstance instead of LinuxMshv directly.
Fix inner_hypervisor.rs check() to use simple /dev/mshv existence check.

Override standard_rust_check in runtime-rs Makefile to use explicit
features instead of --all-features (dragonball and openvmm have
incompatible kvm-ioctls versions). Exclude dragonball crates from
test target when openvmm is enabled.

Signed-off-by: Aurélien Bombo <abombo@microsoft.com>
Implement the full VM boot sequence in inner_hypervisor.rs:
- Build kernel cmdline with rootfs, console, and cgroup params
- Open kernel file and construct LoadMode::Linux (ACPI boot mode)
- Build HyperVGen2LinuxDirect chipset via VmManifestBuilder
- Configure PCIe root complex with one port for virtio-blk-pci rootfs
- Set up memory, processor topology, and hvsocket for agent comm
- Launch VmWorker via mesh_worker and resume (boot) the VM

Also implement stop_vm (via VmmInstance::stop), pause_vm, resume_vm,
and proper get_agent_socket returning hvsock:// URI.

Add memory_range workspace dependency for PCIe MMIO range config.

Signed-off-by: Aurélien Bombo <abombo@microsoft.com>
Fix ECAM range size assertion by setting end_bus=127 to match the
128MB ECAM range (0xe8000000..0xf0000000). The assertion in pcie/
root.rs requires ecam_size_from_bus_numbers == ecam_range.len().

Add 'extern crate openvmm_resources as _' to force the linker to
include the VmWorker registration via linkme::distributed_slice.
Without this, the worker factory returns 'unsupported worker VmWorker'.

Allow deprecated warnings in RUSTFLAGS for upstream openvmm code
(storvsp try_next deprecation).

The VM now boots successfully in-process via mesh_worker. Pending
devices (vsock, network, virtiofs) are not yet wired into the Config.

Signed-off-by: Aurélien Bombo <abombo@microsoft.com>
Process pending devices in start_vm() to include them in the Config:
- Vsock: configured via VmbusConfig.vsock_path
- Network: create NetvspHandle with TapHandle backend
- ShareFs: create VirtioFsHandle on PCIe port rp1
- Block: skip duplicate (already added as rootfs)

Bind Unix listener for hvsock at the sandbox path before launching
the VM worker. Enable net_tap feature on openvmm_resources.

Remove --locked from clippy to allow Cargo.lock updates.

Current status: VM boots with all devices, hvsock socket exists,
but agent handshake fails due to protocol mismatch between kata's
hybrid vsock protocol and OpenVMM's hvsocket relay.

Signed-off-by: Aurélien Bombo <abombo@microsoft.com>
Add initcall_blacklist=virtio_vsock_init to kernel params to prevent
the virtio-vsock driver from claiming the vsock transport before
hv_sock (needed for Hyper-V socket agent communication).

Actually bind the hvsock UnixListener before launching the VM worker
so the hvsocket relay can accept connections.

Enable net_tap feature on openvmm_resources for TAP network backend.
Remove --locked from clippy to allow Cargo.lock updates.

Current status: VM boots, all devices wired (rootfs, network,
virtio-fs, hvsock), agent client connects to hvsock socket,
but hvsocket relay handshake returns empty response (guest VMBus
or agent not ready yet).

Signed-off-by: Aurélien Bombo <abombo@microsoft.com>
Restore --locked to cargo clippy in standard_rust_check.
Update Cargo.lock to reflect current dependency changes.

Signed-off-by: Aurélien Bombo <abombo@microsoft.com>
Increase reconnect_timeout_ms from 3000 to 45000 in the openvmm
config template to give the guest kernel more time to boot and the
kata-agent to start. The guest takes ~5-6 seconds to boot to agent.

Signed-off-by: Aurélien Bombo <abombo@microsoft.com>
The OpenVMM hvsocket relay expects uppercase 'CONNECT <port>' but
kata's hybrid_vsock.rs was sending lowercase 'connect <port>'. This
caused the relay to reject the handshake with 'invalid connect
request', returning an empty response that kata interpreted as
'malformed response code'.

Change connect_helper() to send 'CONNECT {port}' (uppercase) to
match the Firecracker/OpenVMM hybrid vsock protocol specification.

Signed-off-by: Aurélien Bombo <abombo@microsoft.com>
Add tracing-subscriber dependency for capturing openvmm VmWorker
debug output. Write openvmm worker logs to a file in the sandbox
run directory (openvmm-worker.log).

Pass log_dir to VmmInstance::launch() for tracing setup.
Fix launch call site to pass run_dir as log directory.

Current status: VM boots, no errors, but hvsock relay doesn't respond
to CONNECT requests from in-process integration despite working with
CLI. Investigating pal_async event loop integration.

Signed-off-by: Aurélien Bombo <abombo@microsoft.com>
Bind COM1 serial output to a Unix socket at <run_dir>/console.sock.
This allows debugging guest kernel output by connecting to the socket:
  socat -u UNIX-CONNECT:/run/kata/<id>/console.sock -

Add serial_socket and tracing-subscriber dependencies.
Use VmManifestBuilder::with_serial() to bind the serial port.

Note: Serial output is not yet confirmed working - the serial
socket resolver may need additional investigation.

Signed-off-by: Aurélien Bombo <abombo@microsoft.com>
- Open disk file inside VmWorker thread to avoid FD loss through
  mesh channel serialization (same pattern as hvsock listener)
- Use virtio-net-pci instead of VMBus NetvspHandle since guest
  kernel has CONFIG_VIRTIO_NET=y but CONFIG_HYPERV_NET is not set
- Add rootflags=data=ordered,errors=remount-ro ro to kernel cmdline
  matching CLH behavior for read-only ext4 rootfs
- Add HYPERVISOR_NAME_OPENVMM to save/restore match arms in
  sandbox.rs to fix 'Unsupported hypervisor openvmm' in persist

Signed-off-by: Aurélien Bombo <abombo@microsoft.com>
Copilot AI review requested due to automatic review settings March 26, 2026 21:56
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Implements an initial (PoC/WIP) OpenVMM hypervisor backend for runtime-rs, wiring it into the virt_container runtime and Kata config system, and updating build/test tooling to support the new feature set.

Changes:

  • Add an openvmm hypervisor implementation in runtime-rs/crates/hypervisor, plus feature flags and runtime registration.
  • Introduce an OpenVMM runtime configuration template and Makefile logic to enable/disable OpenVMM builds and tests.
  • Update Rust toolchain/version pins and adjust lint/test invocations to accommodate dependency constraints.

Reviewed changes

Copilot reviewed 29 out of 30 changed files in this pull request and generated 10 comments.

Show a summary per file
File Description
versions.yaml Bumps Rust version metadata to 1.94.
utils.mk Adjusts standard Rust checks (adds --locked, removes cargo check + diff guard).
src/runtime-rs/crates/runtimes/virt_container/src/sandbox.rs Adds OpenVMM to sandbox persist/restore hypervisor dispatch.
src/runtime-rs/crates/runtimes/virt_container/src/lib.rs Registers OpenVMM config plugin and enables OpenVMM hypervisor creation behind feature flag.
src/runtime-rs/crates/runtimes/virt_container/Cargo.toml Adds openvmm feature wiring to hypervisor crate.
src/runtime-rs/crates/runtimes/Cargo.toml Plumbs openvmm feature up to runtimes workspace feature.
src/runtime-rs/crates/hypervisor/src/openvmm/vmm_instance.rs New: wraps OpenVMM in-process worker lifecycle + RPC control.
src/runtime-rs/crates/hypervisor/src/openvmm/mod.rs New: OpenVMM Hypervisor + Persist implementation and API surface.
src/runtime-rs/crates/hypervisor/src/openvmm/inner_hypervisor.rs New: OpenVMM VM prepare/start/stop and device wiring into OpenVMM config.
src/runtime-rs/crates/hypervisor/src/openvmm/inner_device.rs New: OpenVMM device management stubs + pending-device queueing.
src/runtime-rs/crates/hypervisor/src/openvmm/inner.rs New: OpenVMM inner state + save/restore state implementation.
src/runtime-rs/crates/hypervisor/src/lib.rs Exposes OpenVMM module + re-exports OpenVMM hypervisor name behind feature.
src/runtime-rs/crates/hypervisor/src/ch/inner_hypervisor.rs Minor refactor to avoid unwrap() in netns logging.
src/runtime-rs/crates/hypervisor/Cargo.toml Adds OpenVMM optional dependencies + openvmm feature list.
src/runtime-rs/crates/agent/src/sock/hybrid_vsock.rs Changes HybridVsock handshake command casing (connectCONNECT).
src/runtime-rs/config/configuration-openvmm.toml.in New: OpenVMM config template.
src/runtime-rs/config/configuration-cloud-hypervisor.toml.in Changes CLH defaults to enable_debug = true in multiple sections.
src/runtime-rs/Makefile Adds OpenVMM build toggles, test excludes, feature handling, and modifies build flags + checks.
src/runtime-rs/Cargo.toml Adds top-level openvmm feature.
src/libs/kata-types/src/config/mod.rs Exports OpenVMM config types and hypervisor name constant.
src/libs/kata-types/src/config/hypervisor/openvmm.rs New: OpenVMM config plugin (adjust/validate).
src/libs/kata-types/src/config/hypervisor/mod.rs Registers OpenVMM config module/exports.
src/libs/kata-sys-util/src/protection.rs Removes unsafe wrappers around __cpuid calls.
src/libs/kata-sys-util/src/mount.rs Uses NixPath::is_empty() for path emptiness checks.
src/dragonball/dbs_arch/src/x86_64/cpuid/common.rs Removes unsafe wrappers around __get_cpuid_max/__cpuid_count.
src/dragonball/dbs_arch/src/x86_64/cpuid/brand_string.rs Removes unsafe wrappers around host_cpuid calls.
src/dragonball/dbs_allocator/src/interval_tree.rs Refactors option handling to avoid unwrap() patterns.
rust-toolchain.toml Bumps pinned Rust toolchain channel to 1.94.
Cargo.toml Adds OpenVMM path-based workspace dependencies and a global bitvec crates.io patch override.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +82 to +88
let subscriber = tracing_subscriber::fmt()
.with_writer(std::sync::Mutex::new(file))
.with_ansi(false)
.finish();
// Use set_default (thread-local) not set_global_default
let _guard = tracing::subscriber::set_default(subscriber);
}
Copy link

Copilot AI Mar 26, 2026

Choose a reason for hiding this comment

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

set_default() returns a guard that must be kept alive for as long as you want the subscriber to be active. Right now _guard is dropped at the end of the if let Some(dir) block, so tracing is effectively disabled for the rest of the worker-host thread. Keep the guard in a variable that lives for the whole thread (or until shutdown), or use a scoped block that covers the entire thread body.

Copilot uses AI. Check for mistakes.
Comment on lines +165 to +169
let _ = result_tx.send(result.context("failed to launch VM worker"));

// Keep the pool alive for the VM's lifetime.
std::future::pending::<()>().await;
});
Copy link

Copilot AI Mar 26, 2026

Choose a reason for hiding this comment

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

The worker-host thread is forced to live forever via std::future::pending().await, but stop() only stops/joins the WorkerHandle and never signals this thread to exit or gets joined itself. This will leak a thread (and the pal_async pool) per VM lifecycle and can accumulate over time. Consider adding an explicit shutdown mechanism for the pool/runner (e.g., cancellation channel), store the thread JoinHandle, and join it during stop().

Copilot uses AI. Check for mistakes.
#
# Default false
enable_debug = false
enable_debug = true
Copy link

Copilot AI Mar 26, 2026

Choose a reason for hiding this comment

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

This flips Cloud Hypervisor's default enable_debug to true (comment above still says "Default false"). Since other hypervisor templates default this to false, this is a behavior/logging change that can increase log volume and impact performance/operational noise. If this is only needed for the OpenVMM PoC, consider keeping CLH defaults unchanged or gate it behind a build-time variable.

Suggested change
enable_debug = true
enable_debug = false

Copilot uses AI. Check for mistakes.
# If enabled, make the agent display debug-level messages.
# (default: disabled)
enable_debug = false
enable_debug = true
Copy link

Copilot AI Mar 26, 2026

Choose a reason for hiding this comment

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

This flips Cloud Hypervisor agent enable_debug to true by default (other templates default to false). If this isn't intentional for CLH generally, revert to false or make it configurable via a template variable so enabling debug remains an explicit choice.

Suggested change
enable_debug = true
enable_debug = false

Copilot uses AI. Check for mistakes.
# system log
# (default: disabled)
enable_debug = false
enable_debug = true
Copy link

Copilot AI Mar 26, 2026

Choose a reason for hiding this comment

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

This flips Cloud Hypervisor runtime enable_debug to true by default (other templates default to false). Unless CLH specifically needs debug always on, consider reverting or gating to avoid increased log volume and potential performance impact in production deployments.

Suggested change
enable_debug = true
enable_debug = false

Copilot uses AI. Check for mistakes.
Comment on lines +23 to +25

const KATA_PATH: &str = "/run/kata";

Copy link

Copilot AI Mar 26, 2026

Choose a reason for hiding this comment

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

OpenVMM introduces a local KATA_PATH constant hardcoded to /run/kata. Other hypervisors use kata_types::config::KATA_PATH, which centralizes this value and avoids divergence. Consider reusing the shared constant instead of duplicating it here.

Suggested change
const KATA_PATH: &str = "/run/kata";
use kata_types::config::KATA_PATH;

Copilot uses AI. Check for mistakes.
Comment thread rust-toolchain.toml
@@ -1,3 +1,3 @@
[toolchain]
# Keep in sync with versions.yaml
Copy link

Copilot AI Mar 26, 2026

Choose a reason for hiding this comment

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

This bumps the pinned toolchain to 1.94, but the workspace Cargo.toml still declares rust-version = "1.88" (MSRV). If 1.94 is now the project minimum, update rust-version accordingly; if 1.88 remains the MSRV, consider clarifying the intent (toolchain pin vs MSRV) to avoid confusion and CI inconsistencies.

Suggested change
# Keep in sync with versions.yaml
# Keep in sync with versions.yaml.
# Note: This pinned CI toolchain is not the MSRV; the MSRV is defined
# in the workspace Cargo.toml (currently `rust-version = "1.88"`).

Copilot uses AI. Check for mistakes.
Comment thread Cargo.toml
Comment on lines +102 to +121
virt_mshv = { path = "../openvmm-repo/vmm_core/virt_mshv" }
openvmm_core = { path = "../openvmm-repo/openvmm/openvmm_core" }
openvmm_defs = { path = "../openvmm-repo/openvmm/openvmm_defs" }
openvmm_resources = { path = "../openvmm-repo/openvmm/openvmm_resources", features = ["virt_mshv", "net_tap"] }
openvmm_helpers = { path = "../openvmm-repo/openvmm/openvmm_helpers" }
vm_manifest_builder = { path = "../openvmm-repo/vmm_core/vm_manifest_builder" }
ovmm_mesh = { path = "../openvmm-repo/support/mesh", package = "mesh" }
ovmm_mesh_worker = { path = "../openvmm-repo/support/mesh/mesh_worker", package = "mesh_worker" }
ovmm_pal_async = { path = "../openvmm-repo/support/pal/pal_async", package = "pal_async" }
ovmm_unix_socket = { path = "../openvmm-repo/support/unix_socket", package = "unix_socket", features = ["mesh"] }
storvsp_resources = { path = "../openvmm-repo/vm/devices/storage/storvsp_resources" }
scsidisk_resources = { path = "../openvmm-repo/vm/devices/storage/scsidisk_resources" }
netvsp_resources = { path = "../openvmm-repo/vm/devices/net/netvsp_resources" }
net_backend_resources = { path = "../openvmm-repo/vm/devices/net/net_backend_resources" }
virtio_resources = { path = "../openvmm-repo/vm/devices/virtio/virtio_resources" }
vm_resource = { path = "../openvmm-repo/vm/vmcore/vm_resource" }
disk_backend_resources = { path = "../openvmm-repo/vm/devices/storage/disk_backend_resources" }
ovmm_vmm_core_defs = { path = "../openvmm-repo/vmm_core/vmm_core_defs", package = "vmm_core_defs" }
ovmm_guid = { path = "../openvmm-repo/support/guid", package = "guid" }
ovmm_memory_range = { path = "../openvmm-repo/vm/vmcore/memory_range", package = "memory_range" }
Copy link

Copilot AI Mar 26, 2026

Choose a reason for hiding this comment

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

These OpenVMM workspace dependencies point to ../openvmm-repo/... outside this repository. That makes builds non-reproducible and will fail in CI/developer setups unless that exact sibling checkout exists. Prefer using a git dependency (with a pinned rev), vendoring, or adding the external repo as a submodule/path inside this repo (and gating resolution behind a feature if possible).

Suggested change
virt_mshv = { path = "../openvmm-repo/vmm_core/virt_mshv" }
openvmm_core = { path = "../openvmm-repo/openvmm/openvmm_core" }
openvmm_defs = { path = "../openvmm-repo/openvmm/openvmm_defs" }
openvmm_resources = { path = "../openvmm-repo/openvmm/openvmm_resources", features = ["virt_mshv", "net_tap"] }
openvmm_helpers = { path = "../openvmm-repo/openvmm/openvmm_helpers" }
vm_manifest_builder = { path = "../openvmm-repo/vmm_core/vm_manifest_builder" }
ovmm_mesh = { path = "../openvmm-repo/support/mesh", package = "mesh" }
ovmm_mesh_worker = { path = "../openvmm-repo/support/mesh/mesh_worker", package = "mesh_worker" }
ovmm_pal_async = { path = "../openvmm-repo/support/pal/pal_async", package = "pal_async" }
ovmm_unix_socket = { path = "../openvmm-repo/support/unix_socket", package = "unix_socket", features = ["mesh"] }
storvsp_resources = { path = "../openvmm-repo/vm/devices/storage/storvsp_resources" }
scsidisk_resources = { path = "../openvmm-repo/vm/devices/storage/scsidisk_resources" }
netvsp_resources = { path = "../openvmm-repo/vm/devices/net/netvsp_resources" }
net_backend_resources = { path = "../openvmm-repo/vm/devices/net/net_backend_resources" }
virtio_resources = { path = "../openvmm-repo/vm/devices/virtio/virtio_resources" }
vm_resource = { path = "../openvmm-repo/vm/vmcore/vm_resource" }
disk_backend_resources = { path = "../openvmm-repo/vm/devices/storage/disk_backend_resources" }
ovmm_vmm_core_defs = { path = "../openvmm-repo/vmm_core/vmm_core_defs", package = "vmm_core_defs" }
ovmm_guid = { path = "../openvmm-repo/support/guid", package = "guid" }
ovmm_memory_range = { path = "../openvmm-repo/vm/vmcore/memory_range", package = "memory_range" }
virt_mshv = { git = "https://github.com/microsoft/openvmm", rev = "PUT_REAL_OPENVMM_COMMIT_HASH_HERE", package = "virt_mshv" }
openvmm_core = { git = "https://github.com/microsoft/openvmm", rev = "PUT_REAL_OPENVMM_COMMIT_HASH_HERE", package = "openvmm_core" }
openvmm_defs = { git = "https://github.com/microsoft/openvmm", rev = "PUT_REAL_OPENVMM_COMMIT_HASH_HERE", package = "openvmm_defs" }
openvmm_resources = { git = "https://github.com/microsoft/openvmm", rev = "PUT_REAL_OPENVMM_COMMIT_HASH_HERE", package = "openvmm_resources", features = ["virt_mshv", "net_tap"] }
openvmm_helpers = { git = "https://github.com/microsoft/openvmm", rev = "PUT_REAL_OPENVMM_COMMIT_HASH_HERE", package = "openvmm_helpers" }
vm_manifest_builder = { git = "https://github.com/microsoft/openvmm", rev = "PUT_REAL_OPENVMM_COMMIT_HASH_HERE", package = "vm_manifest_builder" }
ovmm_mesh = { git = "https://github.com/microsoft/openvmm", rev = "PUT_REAL_OPENVMM_COMMIT_HASH_HERE", package = "mesh" }
ovmm_mesh_worker = { git = "https://github.com/microsoft/openvmm", rev = "PUT_REAL_OPENVMM_COMMIT_HASH_HERE", package = "mesh_worker" }
ovmm_pal_async = { git = "https://github.com/microsoft/openvmm", rev = "PUT_REAL_OPENVMM_COMMIT_HASH_HERE", package = "pal_async" }
ovmm_unix_socket = { git = "https://github.com/microsoft/openvmm", rev = "PUT_REAL_OPENVMM_COMMIT_HASH_HERE", package = "unix_socket", features = ["mesh"] }
storvsp_resources = { git = "https://github.com/microsoft/openvmm", rev = "PUT_REAL_OPENVMM_COMMIT_HASH_HERE", package = "storvsp_resources" }
scsidisk_resources = { git = "https://github.com/microsoft/openvmm", rev = "PUT_REAL_OPENVMM_COMMIT_HASH_HERE", package = "scsidisk_resources" }
netvsp_resources = { git = "https://github.com/microsoft/openvmm", rev = "PUT_REAL_OPENVMM_COMMIT_HASH_HERE", package = "netvsp_resources" }
net_backend_resources = { git = "https://github.com/microsoft/openvmm", rev = "PUT_REAL_OPENVMM_COMMIT_HASH_HERE", package = "net_backend_resources" }
virtio_resources = { git = "https://github.com/microsoft/openvmm", rev = "PUT_REAL_OPENVMM_COMMIT_HASH_HERE", package = "virtio_resources" }
vm_resource = { git = "https://github.com/microsoft/openvmm", rev = "PUT_REAL_OPENVMM_COMMIT_HASH_HERE", package = "vm_resource" }
disk_backend_resources = { git = "https://github.com/microsoft/openvmm", rev = "PUT_REAL_OPENVMM_COMMIT_HASH_HERE", package = "disk_backend_resources" }
ovmm_vmm_core_defs = { git = "https://github.com/microsoft/openvmm", rev = "PUT_REAL_OPENVMM_COMMIT_HASH_HERE", package = "vmm_core_defs" }
ovmm_guid = { git = "https://github.com/microsoft/openvmm", rev = "PUT_REAL_OPENVMM_COMMIT_HASH_HERE", package = "guid" }
ovmm_memory_range = { git = "https://github.com/microsoft/openvmm", rev = "PUT_REAL_OPENVMM_COMMIT_HASH_HERE", package = "memory_range" }

Copilot uses AI. Check for mistakes.
Comment thread Cargo.toml
Comment on lines +168 to +169
# Pending <https://github.com/ferrilab/bitvec/pull/273>
bitvec = { git = "https://github.com/smalis-msft/bitvec", branch = "set-aliased-previous-val" }
Copy link

Copilot AI Mar 26, 2026

Choose a reason for hiding this comment

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

[patch.crates-io] globally overrides bitvec for the entire workspace to a fork/branch. This can unexpectedly affect non-OpenVMM builds and complicates supply-chain/auditability. If this patch is truly required, consider pinning to an immutable commit SHA, documenting the rationale, and/or isolating the override (e.g., via a forked crate name or upstreaming) rather than globally patching crates.io.

Suggested change
# Pending <https://github.com/ferrilab/bitvec/pull/273>
bitvec = { git = "https://github.com/smalis-msft/bitvec", branch = "set-aliased-previous-val" }
# Pending <https://github.com/ferrilab/bitvec/pull/273>; pinned to a specific commit for reproducibility/auditability
bitvec = { git = "https://github.com/smalis-msft/bitvec", rev = "0123456789abcdef0123456789abcdef01234567" }

Copilot uses AI. Check for mistakes.
Comment thread src/runtime-rs/Makefile

$(TARGET_PATH): $(SOURCES) | show-summary
@RUSTFLAGS="$(EXTRA_RUSTFLAGS) --deny warnings" cargo build --target $(TRIPLE) $(if $(findstring release,$(BUILD_TYPE)),--release) $(EXTRA_RUSTFEATURES)
@RUSTFLAGS="$(EXTRA_RUSTFLAGS) --deny warnings --allow deprecated" cargo build --target $(TRIPLE) $(if $(findstring release,$(BUILD_TYPE)),--release) $(EXTRA_RUSTFEATURES)
Copy link

Copilot AI Mar 26, 2026

Choose a reason for hiding this comment

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

Adding --allow deprecated while also using --deny warnings effectively turns off the deprecation warnings across the whole runtime build, which can hide real maintenance issues unrelated to OpenVMM. Consider scoping this relaxation to just the OpenVMM feature/build path (or addressing the deprecations in dependencies) so other configurations keep strict warning hygiene.

Suggested change
@RUSTFLAGS="$(EXTRA_RUSTFLAGS) --deny warnings --allow deprecated" cargo build --target $(TRIPLE) $(if $(findstring release,$(BUILD_TYPE)),--release) $(EXTRA_RUSTFEATURES)
@RUSTFLAGS="$(EXTRA_RUSTFLAGS) --deny warnings" cargo build --target $(TRIPLE) $(if $(findstring release,$(BUILD_TYPE)),--release) $(EXTRA_RUSTFEATURES)

Copilot uses AI. Check for mistakes.
sprt added 2 commits April 1, 2026 11:25
VmWorkerParameters.hypervisor changed from Option<Resource<HypervisorKind>>
to Resource<HypervisorKind>. Use MshvHandle.into_resource() to explicitly
select the MSHV backend. Added hypervisor_resources as a new dependency.

Signed-off-by: Aurélien Bombo <abombo@microsoft.com>
Replace the VMBus hvsock relay with a virtio-vsock PCIe device
(VirtioVsockHandle on rp3) now that OpenVMM supports virtio-vsock.

- Remove initcall_blacklist=virtio_vsock_init from kernel params
- Remove VMBus vsock_path/vsock_listener config
- Bind virtio-vsock UnixListener inside worker thread (FD pattern)
- Add VirtioVsockHandle as PCIe device with guest CID 3
- Update get_agent_socket() to use vsock.sock path
- The hvsock:// scheme still works — OpenVMM's virtio-vsock uses
  the same CONNECT/OK handshake on its host listener socket

Signed-off-by: Aurélien Bombo <abombo@microsoft.com>
Use virtio-console (hvc0) instead of serial (ttyS0) for guest kernel
and agent log output. This improves boot performance.

- Set enable_serial: false in LoadMode, disable COM1
- Add VirtioConsoleHandle as PCIe device on rp4
- Change kernel console param from console=ttyS0 to console=hvc0
- Same socket-pair-to-journalctl logging pattern as before

Signed-off-by: Aurélien Bombo <abombo@microsoft.com>
sprt added 7 commits April 2, 2026 09:49
Restore openvmm kernel cmdline assembly to use Kata's shared runtime-rs
defaults and rootfs parameter handling so the guest boots the
kata-containers.target path instead of diverging from the other VMMs.

Also enter the sandbox network namespace in the VM worker before
resolving the named tap device so tcfilter networking is set up from the
correct namespace during launch.

Signed-off-by: Aurélien Bombo <abombo@microsoft.com>
Teach the OpenVMM runtime-rs integration to reserve PCIe
hotplug ports for block devices, defer non-rootfs block
devices until after boot, and use the block-device-backed
disk handle for host block devices.

This captures the Kata-side changes needed for the Kubernetes
block-volume test fix without including the local Makefile
configuration change.
Signed-off-by: Aurélien Bombo <abombo@microsoft.com>
Signed-off-by: Aurélien Bombo <abombo@microsoft.com>
Queue boot-time virtio-net setup from the outer OpenVMM config path into
the worker thread so the TAP device is opened only after the worker
enters the sandbox network namespace.

OpenVMM now expects a pre-opened TAP fd, so opening the TAP during outer
config assembly bypasses the earlier worker-netns fix and can hit
Device or resource busy failures in focused Kubernetes tests.
The OpenVMM integration in this tree uses path dependencies into the
local ../openvmm-repo checkout. The current OpenVMM branch resolves a
slightly different dependency graph, so building runtime-rs refreshes
Cargo.lock.

Commit the updated lockfile so the tested build stays reproducible
without local lockfile regeneration.
Copilot AI review requested due to automatic review settings April 9, 2026 20:11
Copy link
Copy Markdown

Copilot AI left a comment

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 29 out of 30 changed files in this pull request and generated 13 comments.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread Cargo.toml
Comment on lines +170 to +171
# Pending <https://github.com/ferrilab/bitvec/pull/273>
bitvec = { git = "https://github.com/smalis-msft/bitvec", branch = "set-aliased-previous-val" }
Copy link

Copilot AI Apr 9, 2026

Choose a reason for hiding this comment

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

The [patch.crates-io] override pulls bitvec from a personal GitHub branch. This is a supply-chain/reproducibility risk and can break offline or audited builds. Prefer a crates.io release (once available) or a pinned git revision with a long-lived upstream fork, and document why the patch is required and when it can be removed.

Suggested change
# Pending <https://github.com/ferrilab/bitvec/pull/273>
bitvec = { git = "https://github.com/smalis-msft/bitvec", branch = "set-aliased-previous-val" }
# Temporary workaround for OpenVMM until the upstream fix from
# <https://github.com/ferrilab/bitvec/pull/273> is released on crates.io.
# Keep this pinned to the exact tested commit to preserve reproducible/auditable
# builds, and remove this patch once a crates.io release includes the fix.
bitvec = { git = "https://github.com/smalis-msft/bitvec", rev = "REPLACE_WITH_TESTED_BITVEC_COMMIT" }

Copilot uses AI. Check for mistakes.
Comment thread versions.yaml
Comment on lines 476 to +484
description: "Rust language"
notes: "'version' is the default minimum version used by this project."
# Keep in sync with rust-toolchain.toml
version: "1.91"
version: "1.94"
meta:
description: |
'newest-version' is the latest version known to work when
building Kata
newest-version: "1.91"
newest-version: "1.94"
Copy link

Copilot AI Apr 9, 2026

Choose a reason for hiding this comment

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

versions.yaml and rust-toolchain.toml are bumped to Rust 1.94, but the workspace Cargo.toml still declares rust-version = "1.88". If 1.94 is now the project minimum, update rust-version as well; otherwise, consider keeping versions/toolchain aligned with the declared MSRV to avoid confusion and CI drift.

Copilot uses AI. Check for mistakes.
Comment thread utils.mk
Comment on lines +184 to 186
cargo clippy --all-targets --all-features --release --locked \
-- \
-D warnings
Copy link

Copilot AI Apr 9, 2026

Choose a reason for hiding this comment

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

standard_rust_check runs cargo clippy --all-features at the repo root. With the new openvmm feature (and its note about dragonball incompatibility / external path deps), --all-features is likely to select incompatible feature combinations and/or require unavailable local checkouts, breaking the standard check target. Consider switching to an explicit feature matrix (separate clippy runs per supported hypervisor feature) or defining mutually-exclusive features so --all-features remains valid.

Suggested change
cargo clippy --all-targets --all-features --release --locked \
-- \
-D warnings
cargo clippy --all-targets --release --locked \
-- \
-D warnings
cargo clippy --all-targets --release --locked --no-default-features --features dragonball \
-- \
-D warnings
cargo clippy --all-targets --release --locked --no-default-features --features qemu \
-- \
-D warnings
cargo clippy --all-targets --release --locked --no-default-features --features cloud-hypervisor \
-- \
-D warnings
cargo clippy --all-targets --release --locked --no-default-features --features firecracker \
-- \
-D warnings

Copilot uses AI. Check for mistakes.
Comment on lines 227 to 232
# This option changes the default hypervisor and kernel parameters
# to enable debug output where available.
#
# Default false
enable_debug = false
enable_debug = true

Copy link

Copilot AI Apr 9, 2026

Choose a reason for hiding this comment

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

This change flips Cloud Hypervisor’s config template defaults to enable_debug = true for hypervisor/agent/runtime. That’s a noisy/behavioral change unrelated to the OpenVMM PoC and may not be appropriate as a new default. Consider reverting these defaults (or gating them behind a separate debug profile) so existing users aren’t surprised by increased logging.

Copilot uses AI. Check for mistakes.
Comment on lines +141 to +166
// Build chipset via VmManifestBuilder
let chipset = vm_manifest_builder::VmManifestBuilder::new(
vm_manifest_builder::BaseChipsetType::HyperVGen2LinuxDirect,
vm_manifest_builder::MachineArch::X86_64,
)
.with_serial(serial_ports)
.build()
.context("failed to build VM chipset manifest")?;

// Memory config
let mem_size_bytes = (self.config.memory_info.default_memory as u64)
.checked_mul(1024 * 1024)
.context("memory size overflow")?;

// PCIe root complex: ECAM range must match bus count.
// 128MB ECAM = 128 buses (0..127), each bus has 256 devfns * 4KB config = 1MB.
let pcie_root_complexes = vec![PcieRootComplexConfig {
index: 0,
name: "rc0".to_string(),
segment: 0,
start_bus: 0,
end_bus: 127,
ecam_range: ovmm_memory_range::MemoryRange::new(0xe800_0000..0xf000_0000),
low_mmio: ovmm_memory_range::MemoryRange::new(0xc000_0000..0xd400_0000),
high_mmio: ovmm_memory_range::MemoryRange::new(0x0020_3d30_0000..0x200f_3d30_0000),
ports: {
Copy link

Copilot AI Apr 9, 2026

Choose a reason for hiding this comment

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

ARCH_SUPPORT_OPENVMM includes aarch64, but the OpenVMM implementation currently hard-codes x86_64 specifics (e.g. MachineArch::X86_64, DEFAULT_MMIO_GAPS_X86, and x86 MMIO/ECAM ranges). This will break (or misconfigure) OpenVMM on aarch64. Either restrict OpenVMM support to x86_64 in the build logic, or add proper aarch64 chipset/memory/PCIe configuration paths.

Copilot uses AI. Check for mistakes.
Comment on lines +42 to +82
let port = self.reserve_block_hotplug_port(&block.device_id)?;
let hotplug_result = async {
let metadata = std::fs::metadata(&block.config.path_on_host).with_context(|| {
format!(
"failed to stat block device path {}",
block.config.path_on_host
)
})?;

let disk = if metadata.file_type().is_block_device() {
disk_blockdevice::OpenBlockDeviceConfig {
file: disk_blockdevice::open_file_for_block(
std::path::Path::new(&block.config.path_on_host),
block.config.is_readonly,
)
.with_context(|| {
format!(
"failed to open host block device {}",
block.config.path_on_host
)
})?,
}
.into_resource()
} else {
let mut options = std::fs::OpenOptions::new();
options.read(true);
if !block.config.is_readonly {
options.write(true);
}

let file = options
.open(&block.config.path_on_host)
.with_context(|| {
format!(
"failed to open block device path {}",
block.config.path_on_host
)
})?;

disk_backend_resources::FileDiskHandle(file).into_resource()
};
Copy link

Copilot AI Apr 9, 2026

Choose a reason for hiding this comment

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

This hotplug path opens a file/blk device in the runtime thread and sends the resulting resource over the mesh RPC. However, the OpenVMM launch path explicitly avoids passing FDs over mesh channels (“FD loss through mesh channel serialization”) by opening the disk in the worker thread. If the same FD-serialization limitation applies here, block hotplug will be unreliable. Consider passing only the path over RPC and opening the FD inside the worker thread (or confirm and document that RPC supports FD transfer safely).

Copilot uses AI. Check for mistakes.
Comment on lines +136 to +153
let Some(port) = self.release_block_hotplug_port(&block.device_id) else {
warn!(
sl!(),
"openvmm: no hotplug mapping found for block device {}",
block.device_id
);
return Ok(());
};

self.vmm_instance
.remove_pcie_device(port.name.clone())
.await
.with_context(|| {
format!(
"failed to hot-remove block device {} from {}",
block.device_id, port.name
)
})?;
Copy link

Copilot AI Apr 9, 2026

Choose a reason for hiding this comment

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

remove_device() releases the reserved hotplug port mapping before attempting the actual hot-remove RPC. If the RPC fails, the mapping/port reservation is lost and the runtime can get out of sync with the VM state. Consider only releasing the port after a successful remove_pcie_device, or restoring the mapping on failure.

Copilot uses AI. Check for mistakes.
Comment on lines +408 to +410
let hypervisor = config.hypervisor.get(HYPERVISOR_NAME).unwrap();
assert!((hypervisor.cpu_info.default_vcpus - (0.75 + 1.2)).abs() < f32::EPSILON);
assert_eq!(hypervisor.memory_info.default_memory, 2048 + 512);
Copy link

Copilot AI Apr 9, 2026

Choose a reason for hiding this comment

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

This new test compares floating-point vCPU values using f32::EPSILON, which is often too strict for non-trivial arithmetic like 0.75 + 1.2 and can lead to flaky failures due to rounding. Use a larger tolerance (e.g. 1e-6/1e-4) or an approx/assert helper to make the test robust.

Copilot uses AI. Check for mistakes.
Comment thread src/runtime-rs/Makefile
Comment on lines +105 to +112
ARCH_SUPPORT_OPENVMM := x86_64 aarch64
ifneq ($(filter $(ARCH),$(ARCH_SUPPORT_OPENVMM)),)
USE_OPENVMM := true
else
USE_OPENVMM := false
$(info OpenVMM does not support ARCH $(ARCH), disabled. \
Specify "USE_OPENVMM=true" to force enable.)
endif
Copy link

Copilot AI Apr 9, 2026

Choose a reason for hiding this comment

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

The build system advertises OpenVMM support for aarch64, but the current OpenVMM implementation is x86_64-specific (chipset arch, MMIO gaps/ranges, etc.). To avoid enabling a broken configuration, either remove aarch64 from ARCH_SUPPORT_OPENVMM for now or add the required aarch64-specific OpenVMM configuration paths.

Copilot uses AI. Check for mistakes.
Comment thread src/runtime-rs/Makefile
Comment on lines 804 to 806
$(TARGET_PATH): $(SOURCES) | show-summary
@RUSTFLAGS="$(EXTRA_RUSTFLAGS) --deny warnings" cargo build --target $(TRIPLE) $(if $(findstring release,$(BUILD_TYPE)),--release) $(EXTRA_RUSTFEATURES)
@RUSTFLAGS="$(EXTRA_RUSTFLAGS) --deny warnings --allow deprecated" cargo build --target $(TRIPLE) $(if $(findstring release,$(BUILD_TYPE)),--release) $(EXTRA_RUSTFEATURES)

Copy link

Copilot AI Apr 9, 2026

Choose a reason for hiding this comment

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

The build now adds --allow deprecated while still using --deny warnings, which globally suppresses deprecation warnings across the whole runtime build. This can mask important upgrade work and make it harder to notice new deprecations. Prefer fixing the deprecations (or scoping allow(deprecated) to the specific module/uses that require it) and/or only applying this flag when the openvmm feature is enabled.

Copilot uses AI. Check for mistakes.
* Put the loop device creation code in the test itself, so that we get proper
  logs if that part fails (following other tests).

* Reuse the $node variable to fix the test on multi-node clusters.

Signed-off-by: Aurélien Bombo <abombo@microsoft.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants