Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 8 additions & 2 deletions .github/workflows/openvmm-ci.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

10 changes: 8 additions & 2 deletions .github/workflows/openvmm-pr-release.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

10 changes: 8 additions & 2 deletions .github/workflows/openvmm-pr.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions Cargo.lock
Original file line number Diff line number Diff line change
Expand Up @@ -9831,11 +9831,13 @@ dependencies = [
"hybrid_vsock",
"inspect",
"mesh",
"nix 0.30.1",
"open_enum",
"pal_async",
"pal_event",
"parking_lot",
"smallvec",
"sparse_mmap",
"task_control",
"tempfile",
"test_with_tracing",
Expand Down
11 changes: 11 additions & 0 deletions Guide/src/reference/openvmm/management/cli.md
Original file line number Diff line number Diff line change
Expand Up @@ -159,6 +159,17 @@ as well as the generated CLI help (via `cargo run -- --help`).
The guest kernel must have `CONFIG_HW_RANDOM_VIRTIO` enabled.
* `--virtio-rng-bus <BUS>`: Select the bus for the virtio-rng device (`auto`, `mmio`, `pci`, `vpci`).
Defaults to `auto`.
* `--virtio-vsock-path <PATH>`: Add a virtio-vsock device using OpenVMM's
hybrid Unix-socket relay.
* `--virtio-vsock-vhost-cid <CID>`: Add a virtio-vsock device backed by the
Linux kernel's `vhost_vsock` implementation. This makes the guest reachable
from host applications through `AF_VSOCK` at `CID`, which must be between 3
and 4294967294 (CIDs 0-2 are reserved for the hypervisor, loopback, and host,
respectively, and u32::MAX is the ANY wildcard). This option requires
`/dev/vhost-vsock`, the `vhost_vsock` kernel module, and shared file-backed
guest RAM (the default memory backing). It uses identity-mapped DMA and
does not support a non-identity virtual IOMMU. It conflicts with
`--virtio-vsock-path`.
* `--vhost-user <SOCKET_PATH>,type=<TYPE>[,tag=<NAME>][,num_queues=<N>][,queue_size=<N>][,pcie_port=<PORT>]`: Attach a
vhost-user device backed by an external process over a Unix socket (Linux
only). The backend process must already be listening on `SOCKET_PATH`.
Expand Down
4 changes: 3 additions & 1 deletion ci-flowey/openvmm-pr.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
Expand Up @@ -288,6 +288,12 @@ impl SimpleFlowNode for Node {
register_prep_steps.claim_unused(ctx);
}

let prepare_vhost_vsock = incubator_profile.is_none()
&& matches!(
target.operating_system,
target_lexicon::OperatingSystem::Linux
)
&& matches!(target.architecture, target_lexicon::Architecture::X86_64);
let (extra_env, nextest_working_dir, nextest_config_file) = if let Some(profile_name) =
incubator_profile
{
Expand Down Expand Up @@ -368,6 +374,7 @@ impl SimpleFlowNode for Node {
extra_env,
pre_run_deps,
hugetlb_2mb_overcommit_pages,
prepare_vhost_vsock,
results: v,
});

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -952,6 +952,7 @@ impl SimpleFlowNode for Node {
extra_env,
pre_run_deps: side_effects,
hugetlb_2mb_overcommit_pages: None,
prepare_vhost_vsock: false,
results: v,
});

Expand Down
26 changes: 26 additions & 0 deletions flowey/flowey_lib_hvlite/src/test_nextest_vmm_tests_archive.rs
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,8 @@ flowey_request! {
pub pre_run_deps: Vec<ReadVar<SideEffect>>,
/// If set, configure this 2 MiB hugetlb surplus page overcommit limit before running tests.
pub hugetlb_2mb_overcommit_pages: Option<u64>,
/// Load vhost-vsock and make `/dev/vhost-vsock` accessible before tests.
pub prepare_vhost_vsock: bool,
/// Results of running the tests
pub results: WriteVar<TestResults>,
}
Expand All @@ -63,6 +65,7 @@ impl SimpleFlowNode for Node {
mut extra_env,
mut pre_run_deps,
hugetlb_2mb_overcommit_pages,
prepare_vhost_vsock,
results,
} = request;

Expand Down Expand Up @@ -136,6 +139,29 @@ impl SimpleFlowNode for Node {
})
});
}

if prepare_vhost_vsock {
pre_run_deps.push({
ctx.emit_rust_step("prepare vhost-vsock", |_| {
|rt| {
flowey::shell_cmd!(rt, "sudo modprobe vhost_vsock").run()?;
for _ in 0..50 {
if Path::new("/dev/vhost-vsock").exists() {
break;
}
std::thread::sleep(std::time::Duration::from_millis(100));
}
if !Path::new("/dev/vhost-vsock").exists() {
anyhow::bail!(
"/dev/vhost-vsock did not appear after loading vhost_vsock"
);
}
flowey::shell_cmd!(rt, "sudo chmod a+rw /dev/vhost-vsock").run()?;
Ok(())
}
})
});
}
}

let nextest_archive = nextest_archive_file.map(ctx, |x| x.archive_file);
Expand Down
41 changes: 41 additions & 0 deletions openvmm/openvmm_entry/src/cli_args.rs
Original file line number Diff line number Diff line change
Expand Up @@ -765,6 +765,17 @@ options:
#[clap(long, value_name = "PATH")]
pub virtio_vsock_path: Option<String>,

/// expose the guest in the host AF_VSOCK namespace using the Linux
/// vhost_vsock kernel backend
#[cfg(target_os = "linux")]
#[clap(
long,
value_name = "CID",
conflicts_with = "virtio_vsock_path",
value_parser = parse_vhost_vsock_cid
)]
pub virtio_vsock_vhost_cid: Option<u32>,

/// expose a virtio network with the given backend (dio | vmnic | tap |
/// none)
///
Expand Down Expand Up @@ -1430,6 +1441,17 @@ pub enum VirtioBusCli {
Vpci,
}

#[cfg(target_os = "linux")]
fn parse_vhost_vsock_cid(value: &str) -> Result<u32, String> {
let cid = value
.parse::<u32>()
.map_err(|error| format!("invalid CID '{value}': {error}"))?;
if !(3..u32::MAX).contains(&cid) {
return Err(format!("CID must be between 3 and {}", u32::MAX - 1));
}
Ok(cid)
}

/// Parse an optional `pcie_port=<name>:` prefix from a CLI argument string.
///
/// Returns `(Some(port_name), rest)` if the prefix is present, or
Expand Down Expand Up @@ -4913,6 +4935,25 @@ mod tests {
assert!(VhostUserCli::from_str("/run/x.sock,device_id=1").is_err()); // device_id without queue_sizes
}

#[cfg(target_os = "linux")]
#[test]
fn test_vhost_vsock_cli() {
let opt = Options::try_parse_from(["openvmm", "--virtio-vsock-vhost-cid", "3"]).unwrap();
assert_eq!(opt.virtio_vsock_vhost_cid, Some(3));

assert!(Options::try_parse_from(["openvmm", "--virtio-vsock-vhost-cid", "2"]).is_err());
assert!(
Options::try_parse_from([
"openvmm",
"--virtio-vsock-vhost-cid",
"3",
"--virtio-vsock-path",
"/tmp/vsock",
])
.is_err()
);
}

#[test]
fn test_nvme_controller_cli_pcie() {
let c = NvmeControllerCli::from_str("id=nvme0,pcie_port=p0").unwrap();
Expand Down
14 changes: 14 additions & 0 deletions openvmm/openvmm_entry/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1889,6 +1889,20 @@ async fn vm_config_from_command_line(
);
}

#[cfg(target_os = "linux")]
if let Some(guest_cid) = opt.virtio_vsock_vhost_cid {
let vhost = std::fs::OpenOptions::new()
.read(true)
.write(true)
.open("/dev/vhost-vsock")
.context("failed to open /dev/vhost-vsock")?
.into();
add_virtio_device(
VirtioBusCli::Auto,
virtio_resources::vsock::VirtioVsockVhostHandle { vhost, guest_cid }.into_resource(),
);
}

let mut cfg = Config {
chipset,
load_mode,
Expand Down
2 changes: 2 additions & 0 deletions openvmm/openvmm_resources/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,8 @@ vm_resource::register_static_resolvers! {
#[cfg(target_os = "linux")]
vhost_user_frontend::resolver::VhostUserFrontendResolver,
virtio_vsock::resolver::VirtioVsockResolver,
#[cfg(target_os = "linux")]
virtio_vsock::resolver::VirtioVsockVhostResolver,

// Vmbus devices
guest_crash_device::resolver::GuestCrashDeviceResolver,
Expand Down
3 changes: 3 additions & 0 deletions petri/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,9 @@ vmsocket.workspace = true
vmswitch.workspace = true
windows-version.workspace = true

[target.'cfg(target_os = "linux")'.dependencies]
vmsocket.workspace = true

[target.'cfg(target_arch = "x86_64")'.dependencies]
hvdef.workspace = true
safe_intrinsics.workspace = true
Expand Down
Loading
Loading