From: colbyt <colby@colbyt.com>
To: devel@spectrum-os.org
Cc: colbyt <colby@colbyt.com>
Subject: [PATCH 2/6] pkgs/cloud-hypervisor: update GPU patchset to v52
Date: Thu, 25 Jun 2026 10:48:45 -0700 [thread overview]
Message-ID: <7cb1c12557f07e353186254250bfea29e36c8f30.1782409229.git.colby@colbyt.com> (raw)
In-Reply-To: <cover.1782409229.git.colby@colbyt.com>
Update Spectrum's patched Cloud Hypervisor package to 52.0 and rebase
the local virtio-gpu/vhost-user GPU support onto that release.
Cloud Hypervisor 52.0 uses vhost 0.16.0 and vhost-user-backend 0.22.0,
so update the paired rust-vmm/vhost checkout as well. The local vhost
shared-memory patches are no longer applied because vhost-user-backend
0.22.0 already has the protocol support used by the GPU frontend.
The cargo vendor derivation now vendors dependencies after applying the
local Cloud Hypervisor and vhost patches, so the patched vhost checkout
is included in the fixed-output dependency tree.
Signed-off-by: colbyt <colby@colbyt.com>
---
.../0001-build-use-local-vhost.patch | 38 +-
...0002-virtio-devices-add-a-GPU-device.patch | 674 ++++++++----------
pkgs/cloud-hypervisor/default.nix | 76 +-
3 files changed, 392 insertions(+), 396 deletions(-)
diff --git a/pkgs/cloud-hypervisor/0001-build-use-local-vhost.patch b/pkgs/cloud-hypervisor/0001-build-use-local-vhost.patch
index 3e00250..8f18b94 100644
--- a/pkgs/cloud-hypervisor/0001-build-use-local-vhost.patch
+++ b/pkgs/cloud-hypervisor/0001-build-use-local-vhost.patch
@@ -1,55 +1,55 @@
From fca364182f5c4e595384297316e9c74069ca5169 Mon Sep 17 00:00:00 2001
From: Alyssa Ross <alyssa.ross@unikie.com>
Date: Wed, 28 Sep 2022 12:18:19 +0000
-Subject: [PATCH 1/2] build: use local vhost
+Subject: [PATCH] build: use local vhost
SPDX-FileCopyrightText: 2022 Unikie
SPDX-FileCopyrightText: 2023 Alyssa Ross <hi@alyssa.is>
SPDX-License-Identifier: Apache-2.0 AND LicenseRef-BSD-3-Clause-Google
Signed-off-by: Alyssa Ross <alyssa.ross@unikie.com>
Signed-off-by: Alyssa Ross <hi@alyssa.is>
+Signed-off-by: colbyt <colby@colbyt.com>
---
Cargo.lock | 4 ----
Cargo.toml | 4 ++--
2 files changed, 2 insertions(+), 6 deletions(-)
diff --git a/Cargo.lock b/Cargo.lock
-index 62bbf709f..39df61015 100644
+index d0a21c5..e7af1c2 100644
--- a/Cargo.lock
+++ b/Cargo.lock
-@@ -2304,8 +2304,6 @@ dependencies = [
+@@ -2408,8 +2408,6 @@ dependencies = [
[[package]]
name = "vhost"
- version = "0.14.0"
+ version = "0.16.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
--checksum = "2a4dcad85a129d97d5d4b2f3c47a4affdeedd76bdcd02094bcb5d9b76cac2d05"
+-checksum = "ee90657203a8644e9a0860a0db6a7887d8ef0c7bc09fc22dfa4ae75df65bac86"
dependencies = [
- "bitflags 2.10.0",
+ "bitflags 2.11.1",
"libc",
-@@ -2317,8 +2315,6 @@ dependencies = [
+@@ -2421,8 +2419,6 @@ dependencies = [
[[package]]
name = "vhost-user-backend"
- version = "0.20.0"
+ version = "0.22.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
--checksum = "e183205a9ba7cb9c47fcb0fc0a07fc295a110efbb11ab78ad0d793b0a38a7bde"
+-checksum = "d5925983d8fb537752ad3e26604c0a17abfa5de77cb6773a096c8a959c9eca0f"
dependencies = [
"libc",
"log",
diff --git a/Cargo.toml b/Cargo.toml
-index b738dde5b..1118f1eb1 100644
+index 3ef574c..197f8fd 100644
--- a/Cargo.toml
+++ b/Cargo.toml
-@@ -55,8 +55,8 @@ seccompiler = "0.5.0"
- vfio-bindings = { version = "0.6.0", default-features = false }
- vfio-ioctls = { version = "0.5.1", default-features = false }
- vfio_user = { version = "0.1.1", default-features = false }
--vhost = { version = "0.14.0", default-features = false }
--vhost-user-backend = { version = "0.20.0", default-features = false }
+@@ -63,8 +63,8 @@ seccompiler = "0.5.0"
+ vfio-bindings = { version = "0.6.2", default-features = false }
+ vfio-ioctls = { version = "0.6.0", default-features = false }
+ vfio_user = { version = "0.1.3", default-features = false }
+-vhost = { version = "0.16.0", default-features = false }
+-vhost-user-backend = { version = "0.22.0", default-features = false }
+vhost = { path = "../vhost/vhost" }
+vhost-user-backend = { path = "../vhost/vhost-user-backend" }
virtio-bindings = "0.2.6"
- virtio-queue = "0.16.0"
+ virtio-queue = "0.17.0"
vm-fdt = "0.3.0"
--
-2.53.0
-
+2.54.0
diff --git a/pkgs/cloud-hypervisor/0002-virtio-devices-add-a-GPU-device.patch b/pkgs/cloud-hypervisor/0002-virtio-devices-add-a-GPU-device.patch
index d53755b..3c6ec13 100644
--- a/pkgs/cloud-hypervisor/0002-virtio-devices-add-a-GPU-device.patch
+++ b/pkgs/cloud-hypervisor/0002-virtio-devices-add-a-GPU-device.patch
@@ -1,7 +1,7 @@
From e4f29830f953c826c0fca137ef87ab3b67ac74ae Mon Sep 17 00:00:00 2001
From: Alyssa Ross <alyssa.ross@unikie.com>
Date: Wed, 7 Sep 2022 14:16:29 +0000
-Subject: [PATCH 2/2] virtio-devices: add a GPU device
+Subject: [PATCH] virtio-devices: add a GPU device
SPDX-FileCopyrightText: The Cloud Hypervisor Authors
SPDX-FileCopyrightText: 2017-2018 The Chromium OS Authors. All rights reserved.
SPDX-FileCopyrightText: 2018 Amazon.com, Inc. or its affiliates. All Rights Reserved.
@@ -26,65 +26,64 @@ Adding a GPU device from the command line looks like this:
Signed-off-by: Alyssa Ross <alyssa.ross@unikie.com>
Co-authored-by: Alyssa Ross <hi@alyssa.is>
Signed-off-by: Alyssa Ross <hi@alyssa.is>
+Signed-off-by: colbyt <colby@colbyt.com>
---
- cloud-hypervisor/src/bin/ch-remote.rs | 46 +-
- cloud-hypervisor/src/main.rs | 12 +-
+ cloud-hypervisor/src/bin/ch-remote.rs | 44 +-
+ cloud-hypervisor/src/main.rs | 9 +-
virtio-devices/src/device.rs | 4 +-
- virtio-devices/src/lib.rs | 4 +-
- virtio-devices/src/seccomp_filters.rs | 16 +
+ virtio-devices/src/lib.rs | 6 +-
+ virtio-devices/src/seccomp_filters.rs | 14 +
virtio-devices/src/transport/pci_device.rs | 4 +-
- virtio-devices/src/vhost_user/gpu.rs | 411 ++++++++++++++++++
- virtio-devices/src/vhost_user/mod.rs | 6 +
- .../src/vhost_user/vu_common_ctrl.rs | 9 +-
+ virtio-devices/src/vhost_user/gpu.rs | 421 ++++++++++++++++++
+ virtio-devices/src/vhost_user/mod.rs | 8 +
+ .../src/vhost_user/vu_common_ctrl.rs | 8 +-
vmm/src/api/dbus/mod.rs | 7 +-
- vmm/src/api/http/http_endpoint.rs | 9 +-
- vmm/src/api/http/mod.rs | 12 +-
- vmm/src/api/mod.rs | 47 +-
- vmm/src/api/openapi/cloud-hypervisor.yaml | 39 ++
- vmm/src/config.rs | 109 +++++
- vmm/src/device_manager.rs | 144 +++++-
- vmm/src/lib.rs | 79 +++-
- vmm/src/vm.rs | 28 +-
- vmm/src/vm_config.rs | 10 +
- 19 files changed, 967 insertions(+), 29 deletions(-)
- create mode 100644 virtio-devices/src/vhost_user/gpu.rs
+ vmm/src/api/http/http_endpoint.rs | 3 +-
+ vmm/src/api/http/mod.rs | 6 +-
+ vmm/src/api/mod.rs | 45 +-
+ vmm/src/api/openapi/cloud-hypervisor.yaml | 42 ++
+ vmm/src/config.rs | 72 +++
+ vmm/src/device_manager.rs | 147 +++++-
+ vmm/src/lib.rs | 77 +++-
+ vmm/src/vm.rs | 26 +-
+ vmm/src/vm_config.rs | 8 +
+ 19 files changed, 933 insertions(+), 18 deletions(-)
+create mode 100644 virtio-devices/src/vhost_user/gpu.rs
REUSE-IgnoreStart
diff --git a/cloud-hypervisor/src/bin/ch-remote.rs b/cloud-hypervisor/src/bin/ch-remote.rs
-index fd48ffab1..680a2b62f 100644
+index 236e743..75845ed 100644
--- a/cloud-hypervisor/src/bin/ch-remote.rs
+++ b/cloud-hypervisor/src/bin/ch-remote.rs
-@@ -22,8 +22,8 @@ use option_parser::{ByteSized, ByteSizedParseError};
+@@ -24,7 +24,7 @@ use option_parser::{ByteSized, ByteSizedParseError};
use thiserror::Error;
use vmm::config::RestoreConfig;
use vmm::vm_config::{
-- DeviceConfig, DiskConfig, FsConfig, NetConfig, PmemConfig, UserDeviceConfig, VdpaConfig,
-- VsockConfig,
-+ DeviceConfig, DiskConfig, FsConfig, GpuConfig, NetConfig, PmemConfig, UserDeviceConfig,
-+ VdpaConfig, VsockConfig,
+- DeviceConfig, DiskConfig, FsConfig, GenericVhostUserConfig, NetConfig, PmemConfig,
++ DeviceConfig, DiskConfig, FsConfig, GenericVhostUserConfig, GpuConfig, NetConfig, PmemConfig,
+ UserDeviceConfig, VdpaConfig, VsockConfig,
};
#[cfg(feature = "dbus_api")]
- use zbus::{proxy, zvariant::Optional};
-@@ -49,6 +49,8 @@ enum Error {
- AddDiskConfig(#[source] vmm::config::Error),
- #[error("Error parsing filesystem syntax")]
+@@ -53,6 +53,8 @@ enum Error {
AddFsConfig(#[source] vmm::config::Error),
+ #[error("Error parsing generic vhost-user syntax")]
+ AddGenericVhostUserConfig(#[source] vmm::config::Error),
+ #[error("Error parsing GPU syntax: {0}")]
+ AddGpuConfig(#[source] vmm::config::Error),
#[error("Error parsing persistent memory syntax")]
AddPmemConfig(#[source] vmm::config::Error),
#[error("Error parsing network syntax")]
-@@ -83,6 +85,7 @@ trait DBusApi1 {
- fn vm_add_device(&self, device_config: &str) -> zbus::Result<Optional<String>>;
- fn vm_add_disk(&self, disk_config: &str) -> zbus::Result<Optional<String>>;
- fn vm_add_fs(&self, fs_config: &str) -> zbus::Result<Optional<String>>;
+@@ -93,6 +95,7 @@ trait DBusApi1 {
+ &self,
+ generic_vhost_user_config: &str,
+ ) -> zbus::Result<Optional<String>>;
+ fn vm_add_gpu(&self, gpu_config: &str) -> zbus::Result<Optional<String>>;
fn vm_add_net(&self, net_config: &str) -> zbus::Result<Optional<String>>;
fn vm_add_pmem(&self, pmem_config: &str) -> zbus::Result<Optional<String>>;
fn vm_add_user_device(&self, vm_add_user_device: &str) -> zbus::Result<Optional<String>>;
-@@ -155,6 +158,10 @@ impl<'a> DBusApi1ProxyBlocking<'a> {
- self.print_response(self.vm_add_fs(fs_config))
+@@ -169,6 +172,10 @@ impl<'a> DBusApi1ProxyBlocking<'a> {
+ self.print_response(self.vm_add_generic_vhost_user(generic_vhost_user_config))
}
+ fn api_vm_add_gpu(&self, gpu_config: &str) -> ApiResult {
@@ -94,9 +93,9 @@ index fd48ffab1..680a2b62f 100644
fn api_vm_add_net(&self, net_config: &str) -> ApiResult {
self.print_response(self.vm_add_net(net_config))
}
-@@ -398,6 +405,17 @@ fn rest_api_do_command(matches: &ArgMatches, socket: &mut UnixStream) -> ApiResu
- simple_api_command(socket, "PUT", "add-fs", Some(&fs_config))
- .map_err(Error::HttpApiClient)
+@@ -428,6 +435,17 @@ fn rest_api_do_command(matches: &ArgMatches, socket: &mut UnixStream) -> ApiResu
+ )
+ .map_err(Error::HttpApiClient)
}
+ Some("add-gpu") => {
+ let gpu_config = add_gpu_config(
@@ -112,9 +111,9 @@ index fd48ffab1..680a2b62f 100644
Some("add-pmem") => {
let pmem_config = add_pmem_config(
matches
-@@ -620,6 +638,16 @@ fn dbus_api_do_command(matches: &ArgMatches, proxy: &DBusApi1ProxyBlocking<'_>)
+@@ -656,6 +674,16 @@ fn dbus_api_do_command(matches: &ArgMatches, proxy: &DBusApi1ProxyBlocking<'_>)
)?;
- proxy.api_vm_add_fs(&fs_config)
+ proxy.api_vm_add_generic_vhost_user(&generic_vhost_user_config)
}
+ Some("add-gpu") => {
+ let gpu_config = add_gpu_config(
@@ -129,8 +128,8 @@ index fd48ffab1..680a2b62f 100644
Some("add-pmem") => {
let pmem_config = add_pmem_config(
matches
-@@ -835,6 +863,13 @@ fn add_fs_config(config: &str) -> Result<String, Error> {
- Ok(fs_config)
+@@ -875,6 +903,13 @@ fn add_generic_vhost_user_config(config: &str) -> Result<String, Error> {
+ Ok(generic_vhost_user_config)
}
+fn add_gpu_config(config: &str) -> Result<String, Error> {
@@ -143,12 +142,12 @@ index fd48ffab1..680a2b62f 100644
fn add_pmem_config(config: &str) -> Result<String, Error> {
let pmem_config = PmemConfig::parse(config).map_err(Error::AddPmemConfig)?;
let pmem_config = serde_json::to_string(&pmem_config).unwrap();
-@@ -981,6 +1016,13 @@ fn get_cli_commands_sorted() -> Box<[Command]> {
+@@ -1026,6 +1061,13 @@ fn get_cli_commands_sorted() -> Box<[Command]> {
.index(1)
- .help(vmm::vm_config::FsConfig::SYNTAX),
+ .help(vmm::vm_config::GenericVhostUserConfig::SYNTAX),
),
+ Command::new("add-gpu")
-+ .about("Add virtio-gpu backed gpu device")
++ .about("Add virtio-gpu backed GPU device")
+ .arg(
+ Arg::new("gpu_config")
+ .index(1)
@@ -158,44 +157,41 @@ index fd48ffab1..680a2b62f 100644
.about("Add network device")
.arg(Arg::new("net_config").index(1).help(NetConfig::SYNTAX)),
diff --git a/cloud-hypervisor/src/main.rs b/cloud-hypervisor/src/main.rs
-index d08293b6e..cde764e8a 100644
+index 5de2e4c..2f5afce 100644
--- a/cloud-hypervisor/src/main.rs
+++ b/cloud-hypervisor/src/main.rs
-@@ -32,9 +32,9 @@ use vmm::vm_config::FwCfgConfig;
- #[cfg(feature = "ivshmem")]
+@@ -33,7 +33,7 @@ use vmm::vm_config::FwCfgConfig;
use vmm::vm_config::IvshmemConfig;
use vmm::vm_config::{
-- BalloonConfig, DeviceConfig, DiskConfig, FsConfig, LandlockConfig, NetConfig, NumaConfig,
-- PciSegmentConfig, PmemConfig, RateLimiterGroupConfig, TpmConfig, UserDeviceConfig, VdpaConfig,
-- VmConfig, VsockConfig,
-+ BalloonConfig, DeviceConfig, DiskConfig, FsConfig, GpuConfig, LandlockConfig, NetConfig,
-+ NumaConfig, PciSegmentConfig, PmemConfig, RateLimiterGroupConfig, TpmConfig, UserDeviceConfig,
-+ VdpaConfig, VmConfig, VsockConfig,
+ BalloonConfig, ConsoleConfig, DeviceConfig, DiskConfig, FsConfig, GenericVhostUserConfig,
+- LandlockConfig, NetConfig, NumaConfig, PciSegmentConfig, PlatformConfig, PmemConfig,
++ GpuConfig, LandlockConfig, NetConfig, NumaConfig, PciSegmentConfig, PlatformConfig, PmemConfig,
+ RateLimiterGroupConfig, RngConfig, SerialConfig, TpmConfig, UserDeviceConfig, VdpaConfig,
+ VmConfig, VsockConfig,
};
- use vmm_sys_util::eventfd::EventFd;
- use vmm_sys_util::signal::block_signal;
-@@ -280,6 +280,11 @@ fn get_cli_options_sorted(
- .help("GDB socket (UNIX domain socket): path=</path/to/a/file>")
- .num_args(1)
- .group("vmm-config"),
+@@ -252,6 +252,12 @@ fn get_cli_options_sorted(
+ .num_args(1..)
+ .action(ArgAction::Append)
+ .group("vm-config"),
+ Arg::new("gpu")
+ .long("gpu")
+ .help(GpuConfig::SYNTAX)
+ .num_args(1..)
++ .action(ArgAction::Append)
+ .group("vm-config"),
#[cfg(feature = "igvm")]
Arg::new("igvm")
.long("igvm")
-@@ -998,6 +1003,7 @@ mod unit_tests {
- },
+@@ -1011,6 +1017,7 @@ mod unit_tests {
balloon: None,
fs: None,
+ generic_vhost_user: None,
+ gpu: None,
pmem: None,
- serial: ConsoleConfig {
- file: None,
+ serial: SerialConfig {
+ common: CommonConsoleConfig {
diff --git a/virtio-devices/src/device.rs b/virtio-devices/src/device.rs
-index f0ed28f51..892bf08ee 100644
+index 4c61ba3..8b44101 100644
--- a/virtio-devices/src/device.rs
+++ b/virtio-devices/src/device.rs
@@ -6,7 +6,7 @@
@@ -206,8 +202,8 @@ index f0ed28f51..892bf08ee 100644
+use std::collections::{BTreeMap, HashMap};
use std::io::Write;
use std::num::Wrapping;
- use std::sync::atomic::{AtomicBool, Ordering};
-@@ -50,7 +50,7 @@ pub struct VirtioSharedMemoryList {
+ use std::sync::atomic::{AtomicBool, AtomicU8, Ordering};
+@@ -58,7 +58,7 @@ pub struct VirtioSharedMemoryList {
pub mem_slot: u32,
pub addr: GuestAddress,
pub mapping: Arc<MmapRegion>,
@@ -215,31 +211,33 @@ index f0ed28f51..892bf08ee 100644
+ pub region_list: BTreeMap<u8, VirtioSharedMemory>,
}
- /// Trait for virtio devices to be driven by a virtio transport.
+ pub struct ActivationContext {
diff --git a/virtio-devices/src/lib.rs b/virtio-devices/src/lib.rs
-index da4f1c91b..4298e23ae 100644
+index 6ac3977..5f8aa61 100644
--- a/virtio-devices/src/lib.rs
+++ b/virtio-devices/src/lib.rs
-@@ -43,7 +43,7 @@ pub use self::block::{Block, BlockState};
+@@ -44,7 +44,7 @@ pub use self::block::{Block, BlockState};
pub use self::console::{Console, ConsoleResizer, Endpoint};
pub use self::device::{
- DmaRemapping, VirtioCommon, VirtioDevice, VirtioInterrupt, VirtioInterruptType,
-- VirtioSharedMemoryList,
-+ VirtioSharedMemory, VirtioSharedMemoryList,
+ ActivationContext, DmaRemapping, VirtioCommon, VirtioDevice, VirtioInterrupt,
+- VirtioInterruptType, VirtioSharedMemoryList,
++ VirtioInterruptType, VirtioSharedMemory, VirtioSharedMemoryList,
};
pub use self::epoll_helper::{
EPOLL_HELPER_EVENT_LAST, EpollHelper, EpollHelperError, EpollHelperHandler,
-@@ -91,6 +91,8 @@ pub enum ActivateError {
+@@ -114,7 +114,9 @@ pub enum ActivateError {
+ VhostUserFsSetup(#[source] vhost_user::Error),
#[error("Failed to setup vhost-user daemon")]
VhostUserSetup(#[source] vhost_user::Error),
- #[error("Failed to create seccomp filter")]
+- #[error("Failed to create seccomp filter")]
++ #[error("Failed to setup vhost-user-gpu daemon")]
+ VhostUserGpuSetup(#[source] vhost_user::Error),
+ #[error("Failed to create seccomp filter: {0}")]
CreateSeccompFilter(#[source] seccompiler::Error),
#[error("Failed to create rate limiter")]
CreateRateLimiter(#[source] std::io::Error),
diff --git a/virtio-devices/src/seccomp_filters.rs b/virtio-devices/src/seccomp_filters.rs
-index 07601b68a..68910c756 100644
+index 73c347e..5531747 100644
--- a/virtio-devices/src/seccomp_filters.rs
+++ b/virtio-devices/src/seccomp_filters.rs
@@ -24,6 +24,7 @@ pub enum Thread {
@@ -247,10 +245,10 @@ index 07601b68a..68910c756 100644
VirtioVhostBlock,
VirtioVhostFs,
+ VirtioVhostGpu,
+ VirtioGenericVhostUser,
VirtioVhostNet,
VirtioVhostNetCtl,
- VirtioVsock,
-@@ -192,6 +193,20 @@ fn virtio_vhost_fs_thread_rules() -> Vec<(i64, Vec<SeccompRule>)> {
+@@ -219,6 +220,18 @@ fn virtio_generic_vhost_user_thread_rules() -> Vec<(i64, Vec<SeccompRule>)> {
]
}
@@ -261,8 +259,6 @@ index 07601b68a..68910c756 100644
+ (libc::SYS_getcwd, vec![]),
+ (libc::SYS_nanosleep, vec![]),
+ (libc::SYS_recvmsg, vec![]),
-+ (libc::SYS_recvmsg, vec![]),
-+ (libc::SYS_sendmsg, vec![]),
+ (libc::SYS_sendmsg, vec![]),
+ (libc::SYS_socket, vec![]),
+ ]
@@ -271,19 +267,19 @@ index 07601b68a..68910c756 100644
fn virtio_vhost_net_ctl_thread_rules() -> Vec<(i64, Vec<SeccompRule>)> {
vec![]
}
-@@ -271,6 +286,7 @@ fn get_seccomp_rules(thread_type: Thread) -> Vec<(i64, Vec<SeccompRule>)> {
+@@ -299,6 +312,7 @@ fn get_seccomp_rules(thread_type: Thread) -> Vec<(i64, Vec<SeccompRule>)> {
Thread::VirtioRng => virtio_rng_thread_rules(),
Thread::VirtioVhostBlock => virtio_vhost_block_thread_rules(),
Thread::VirtioVhostFs => virtio_vhost_fs_thread_rules(),
+ Thread::VirtioVhostGpu => virtio_vhost_gpu_thread_rules(),
+ Thread::VirtioGenericVhostUser => virtio_generic_vhost_user_thread_rules(),
Thread::VirtioVhostNet => virtio_vhost_net_thread_rules(),
Thread::VirtioVhostNetCtl => virtio_vhost_net_ctl_thread_rules(),
- Thread::VirtioVsock => virtio_vsock_thread_rules(),
diff --git a/virtio-devices/src/transport/pci_device.rs b/virtio-devices/src/transport/pci_device.rs
-index 408611e29..08ba91908 100644
+index ac37c58..5b33239 100644
--- a/virtio-devices/src/transport/pci_device.rs
+++ b/virtio-devices/src/transport/pci_device.rs
-@@ -1036,11 +1036,11 @@ impl PciDevice for VirtioPciDevice {
+@@ -1092,11 +1092,11 @@ impl PciDevice for VirtioPciDevice {
PciDeviceError::IoRegistrationFailed(shm_list.addr.raw_value(), e)
})?;
@@ -299,10 +295,10 @@ index 408611e29..08ba91908 100644
);
diff --git a/virtio-devices/src/vhost_user/gpu.rs b/virtio-devices/src/vhost_user/gpu.rs
new file mode 100644
-index 000000000..7eec07ba6
+index 0000000..f04c74a
--- /dev/null
+++ b/virtio-devices/src/vhost_user/gpu.rs
-@@ -0,0 +1,411 @@
+@@ -0,0 +1,421 @@
+// Copyright 2019 Intel Corporation. All Rights Reserved.
+// Copyright 2022 Unikie
+// Copyright 2023 Alyssa Ross <hi@alyssa.is>
@@ -317,8 +313,8 @@ index 000000000..7eec07ba6
+use log::error;
+use seccompiler::SeccompAction;
+use vhost::vhost_user::message::{
-+ VhostSharedMemoryRegion, VhostUserConfigFlags, VhostUserProtocolFeatures, VhostUserShmemMapMsg,
-+ VhostUserShmemUnmapMsg, VhostUserVirtioFeatures,
++ VhostUserConfigFlags, VhostUserMMap, VhostUserMMapFlags, VhostUserProtocolFeatures,
++ VhostUserShMemConfig, VhostUserVirtioFeatures,
+};
+use vhost::vhost_user::{
+ FrontendReqHandler, HandlerResult, VhostUserFrontend, VhostUserFrontendReqHandler,
@@ -327,7 +323,6 @@ index 000000000..7eec07ba6
+ VIRTIO_GPU_F_CONTEXT_INIT, VIRTIO_GPU_F_RESOURCE_BLOB, VIRTIO_GPU_F_RESOURCE_UUID,
+ VIRTIO_GPU_F_VIRGL,
+};
-+use virtio_queue::Queue;
+use vm_device::UserspaceMapping;
+use vm_memory::volatile_memory::PtrGuardMut;
+use vm_memory::{GuestMemoryAtomic, VolatileMemory};
@@ -341,8 +336,8 @@ index 000000000..7eec07ba6
+use crate::vhost_user::VhostUserCommon;
+use crate::{
+ ActivateError, ActivateResult, GuestMemoryMmap, GuestRegionMmap, MmapRegion,
-+ VIRTIO_F_IOMMU_PLATFORM, VIRTIO_F_VERSION_1, VirtioCommon, VirtioDevice, VirtioDeviceType,
-+ VirtioInterrupt, VirtioSharedMemoryList,
++ VIRTIO_F_ACCESS_PLATFORM, VIRTIO_F_VERSION_1, VirtioCommon, VirtioDevice, VirtioDeviceType,
++ VirtioSharedMemoryList,
+};
+
+const QUEUE_SIZES: &[u16] = &[256, 16];
@@ -369,8 +364,16 @@ index 000000000..7eec07ba6
+}
+
+impl VhostUserFrontendReqHandler for BackendReqHandler {
-+ fn shmem_map(&self, req: &VhostUserShmemMapMsg, fd: &dyn AsRawFd) -> HandlerResult<u64> {
++ fn shmem_map(&self, req: &VhostUserMMap, fd: &dyn AsRawFd) -> HandlerResult<u64> {
+ let target = self.ptr_guard_mut(req.shm_offset, req.len)?;
++ let flags = VhostUserMMapFlags::from_bits(req.flags)
++ .ok_or_else(|| io::Error::from_raw_os_error(libc::EINVAL))?;
++ let prot = libc::PROT_READ
++ | if flags.contains(VhostUserMMapFlags::WRITABLE) {
++ libc::PROT_WRITE
++ } else {
++ 0
++ };
+
+ // SAFETY: we've checked we're only giving addr and length
+ // within the region, and are passing MAP_FIXED to ensure they
@@ -379,9 +382,9 @@ index 000000000..7eec07ba6
+ libc::mmap(
+ target.as_ptr().cast(),
+ target.len(),
-+ req.flags.bits() as i32,
++ prot,
+ // https://bugzilla.kernel.org/show_bug.cgi?id=217238
-+ if req.flags.bits() as i32 & libc::PROT_WRITE != 0 {
++ if flags.contains(VhostUserMMapFlags::WRITABLE) {
+ libc::MAP_SHARED
+ } else {
+ libc::MAP_PRIVATE
@@ -398,7 +401,7 @@ index 000000000..7eec07ba6
+ Ok(0)
+ }
+
-+ fn shmem_unmap(&self, req: &VhostUserShmemUnmapMsg) -> HandlerResult<u64> {
++ fn shmem_unmap(&self, req: &VhostUserMMap) -> HandlerResult<u64> {
+ let target = self.ptr_guard_mut(req.shm_offset, req.len)?;
+
+ // SAFETY: we've checked we're only giving addr and length
@@ -445,9 +448,10 @@ index 000000000..7eec07ba6
+ seccomp_action: SeccompAction,
+ exit_evt: EventFd,
+ iommu: bool,
-+ ) -> Result<(Gpu, VhostSharedMemoryRegion)> {
++ ) -> Result<(Gpu, VhostUserShMemConfig)> {
+ // Connect to the vhost-user socket.
-+ let mut vu = VhostUserHandle::connect_vhost_user(false, path, NUM_QUEUES as u64, false)?;
++ let mut vu =
++ VhostUserHandle::connect_vhost_user(false, path, NUM_QUEUES as u64, false, None)?;
+
+ let avail_features = 1 << VIRTIO_F_VERSION_1
+ | 1 << VIRTIO_GPU_F_VIRGL
@@ -458,19 +462,21 @@ index 000000000..7eec07ba6
+
+ let avail_protocol_features = VhostUserProtocolFeatures::CONFIG
+ | VhostUserProtocolFeatures::BACKEND_REQ
-+ | VhostUserProtocolFeatures::SHARED_MEMORY_REGIONS;
++ | VhostUserProtocolFeatures::SHMEM;
+
+ let (acked_features, acked_protocol_features) =
+ vu.negotiate_features_vhost_user(avail_features, avail_protocol_features)?;
+
-+ let shm_regions = vu.get_shared_memory_regions()?;
-+ if shm_regions.len() != 1 {
++ let shm_config = vu.get_shmem_config()?;
++ if shm_config.nregions != 1 {
+ return Err(Error::VhostUserUnexpectedSharedMemoryRegionsCount(
+ 1,
-+ shm_regions.len(),
++ shm_config.nregions as usize,
+ ));
+ }
-+ let shm_region = shm_regions[0];
++ if shm_config.memory_sizes[0] == 0 {
++ return Err(Error::VhostUserInvalidSharedMemoryRegion);
++ }
+
+ Ok((
+ Gpu {
@@ -506,7 +512,7 @@ index 000000000..7eec07ba6
+ exit_evt,
+ iommu,
+ },
-+ shm_region,
++ shm_config,
+ ))
+ }
+
@@ -536,7 +542,7 @@ index 000000000..7eec07ba6
+ fn features(&self) -> u64 {
+ let mut features = self.common.avail_features;
+ if self.iommu {
-+ features |= 1u64 << VIRTIO_F_IOMMU_PLATFORM;
++ features |= 1u64 << VIRTIO_F_ACCESS_PLATFORM;
+ }
+ features
+ }
@@ -564,12 +570,13 @@ index 000000000..7eec07ba6
+ }
+ }
+
-+ fn activate(
-+ &mut self,
-+ mem: GuestMemoryAtomic<GuestMemoryMmap>,
-+ interrupt_cb: Arc<dyn VirtioInterrupt>,
-+ queues: Vec<(usize, Queue, EventFd)>,
-+ ) -> ActivateResult {
++ fn activate(&mut self, context: crate::device::ActivationContext) -> ActivateResult {
++ let crate::device::ActivationContext {
++ mem,
++ interrupt_cb,
++ queues,
++ device_status,
++ } = context;
+ self.common.activate(&queues, interrupt_cb.clone())?;
+ self.guest_memory = Some(mem.clone());
+
@@ -607,7 +614,7 @@ index 000000000..7eec07ba6
+ let mut handler = self.vu_common.activate(
+ mem,
+ &queues,
-+ interrupt_cb,
++ interrupt_cb.clone(),
+ self.common.acked_features,
+ backend_req_handler,
+ kill_evt,
@@ -624,6 +631,8 @@ index 000000000..7eec07ba6
+ Thread::VirtioVhostGpu,
+ &mut epoll_threads,
+ &self.exit_evt,
++ device_status.clone(),
++ interrupt_cb.clone(),
+ move || handler.run(&paused, paused_sync.as_ref().unwrap()),
+ )?;
+ self.epoll_thread = Some(epoll_threads.remove(0));
@@ -632,17 +641,17 @@ index 000000000..7eec07ba6
+ Ok(())
+ }
+
-+ fn reset(&mut self) -> Option<Arc<dyn VirtioInterrupt>> {
++ fn reset(&mut self) {
+ // We first must resume the virtio thread if it was paused.
+ if self.common.pause_evt.take().is_some() {
-+ self.common.resume().ok()?;
++ self.common.resume().ok();
+ }
+
+ if let Some(vu) = &self.vu_common.vu
+ && let Err(e) = vu.lock().unwrap().reset_vhost_user()
+ {
+ error!("Failed to reset vhost-user daemon: {e:?}");
-+ return None;
++ return;
+ }
+
+ if let Some(kill_evt) = self.common.kill_evt.take() {
@@ -651,9 +660,6 @@ index 000000000..7eec07ba6
+ }
+
+ event!("virtio-device", "reset", "id", &self.id);
-+
-+ // Return the interrupt
-+ Some(self.common.interrupt_cb.take().unwrap())
+ }
+
+ fn shutdown(&mut self) {
@@ -715,24 +721,25 @@ index 000000000..7eec07ba6
+ }
+}
diff --git a/virtio-devices/src/vhost_user/mod.rs b/virtio-devices/src/vhost_user/mod.rs
-index 05233a0be..f2e83ff84 100644
+index babc823..76146b3 100644
--- a/virtio-devices/src/vhost_user/mod.rs
+++ b/virtio-devices/src/vhost_user/mod.rs
-@@ -33,11 +33,13 @@ use crate::{
-
+@@ -37,12 +37,14 @@ use crate::{
pub mod blk;
pub mod fs;
+ pub mod generic_vhost_user;
+pub mod gpu;
pub mod net;
pub mod vu_common_ctrl;
pub use self::blk::Blk;
pub use self::fs::*;
+ pub use self::generic_vhost_user::GenericVhostUser;
+pub use self::gpu::*;
pub use self::net::Net;
pub use self::vu_common_ctrl::VhostUserConfig;
-@@ -75,6 +77,8 @@ pub enum Error {
+@@ -82,6 +84,8 @@ pub enum Error {
VhostUserGetQueueMaxNum(#[source] VhostError),
#[error("Get protocol features failed")]
VhostUserGetProtocolFeatures(#[source] VhostError),
@@ -741,36 +748,37 @@ index 05233a0be..f2e83ff84 100644
#[error("Get vring base failed")]
VhostUserGetVringBase(#[source] VhostError),
#[error("Vhost-user Backend not support vhost-user protocol")]
-@@ -123,6 +127,8 @@ pub enum Error {
+@@ -130,6 +134,10 @@ pub enum Error {
VhostUserSetInflight(#[source] VhostError),
#[error("Failed setting the log base")]
VhostUserSetLogBase(#[source] VhostError),
+ #[error("Expected {0} shared memory regions; got {1}")]
+ VhostUserUnexpectedSharedMemoryRegionsCount(usize, usize),
++ #[error("Invalid shared memory region")]
++ VhostUserInvalidSharedMemoryRegion,
#[error("Invalid used address")]
UsedAddress,
#[error("Invalid features provided from vhost-user backend")]
diff --git a/virtio-devices/src/vhost_user/vu_common_ctrl.rs b/virtio-devices/src/vhost_user/vu_common_ctrl.rs
-index 264635149..220b49112 100644
+index 23a37c3..8c668a3 100644
--- a/virtio-devices/src/vhost_user/vu_common_ctrl.rs
+++ b/virtio-devices/src/vhost_user/vu_common_ctrl.rs
-@@ -13,7 +13,8 @@ use std::time::{Duration, Instant};
- use log::{error, info};
- use vhost::vhost_kern::vhost_binding::{VHOST_F_LOG_ALL, VHOST_VRING_F_LOG};
+@@ -14,7 +14,7 @@ use log::{error, info};
+ use vhost::vhost_kern::vhost_binding::VHOST_VRING_F_LOG;
use vhost::vhost_user::message::{
-- VhostUserHeaderFlag, VhostUserInflight, VhostUserProtocolFeatures, VhostUserVirtioFeatures,
-+ VhostSharedMemoryRegion, VhostUserHeaderFlag, VhostUserInflight, VhostUserProtocolFeatures,
-+ VhostUserVirtioFeatures,
+ VhostTransferStateDirection, VhostTransferStatePhase, VhostUserHeaderFlag, VhostUserInflight,
+- VhostUserProtocolFeatures, VhostUserVirtioFeatures,
++ VhostUserProtocolFeatures, VhostUserShMemConfig, VhostUserVirtioFeatures,
};
use vhost::vhost_user::{
Frontend, FrontendReqHandler, VhostUserFrontend, VhostUserFrontendReqHandler,
-@@ -107,6 +108,12 @@ impl VhostUserHandle {
+@@ -114,6 +114,12 @@ impl VhostUserHandle {
.map_err(Error::VhostUserAddMemReg)
}
-+ pub fn get_shared_memory_regions(&self) -> Result<Vec<VhostSharedMemoryRegion>> {
++ pub fn get_shmem_config(&mut self) -> Result<VhostUserShMemConfig> {
+ self.vu
-+ .get_shared_memory_regions()
++ .get_shmem_config()
+ .map_err(Error::VhostUserGetSharedMemoryRegions)
+ }
+
@@ -778,20 +786,20 @@ index 264635149..220b49112 100644
&mut self,
avail_features: u64,
diff --git a/vmm/src/api/dbus/mod.rs b/vmm/src/api/dbus/mod.rs
-index 6f75fb5cd..78275925d 100644
+index ae39feb..aa579e9 100644
--- a/vmm/src/api/dbus/mod.rs
+++ b/vmm/src/api/dbus/mod.rs
@@ -22,7 +22,7 @@ use super::{ApiAction, ApiRequest};
#[cfg(all(target_arch = "x86_64", feature = "guest_debug"))]
use crate::api::VmCoredump;
use crate::api::{
-- AddDisk, Body, VmAddDevice, VmAddFs, VmAddNet, VmAddPmem, VmAddUserDevice, VmAddVdpa,
-+ AddDisk, Body, VmAddDevice, VmAddFs, VmAddGpu, VmAddNet, VmAddPmem, VmAddUserDevice, VmAddVdpa,
- VmAddVsock, VmBoot, VmCounters, VmCreate, VmDelete, VmInfo, VmPause, VmPowerButton, VmReboot,
- VmReceiveMigration, VmRemoveDevice, VmResize, VmResizeZone, VmRestore, VmResume,
- VmSendMigration, VmShutdown, VmSnapshot, VmmPing, VmmShutdown,
-@@ -144,6 +144,11 @@ impl DBusApi {
- self.vm_action(&VmAddFs, fs_config).await
+- AddDisk, Body, VmAddDevice, VmAddFs, VmAddGenericVhostUser, VmAddNet, VmAddPmem,
++ AddDisk, Body, VmAddDevice, VmAddFs, VmAddGenericVhostUser, VmAddGpu, VmAddNet, VmAddPmem,
+ VmAddUserDevice, VmAddVdpa, VmAddVsock, VmBoot, VmCounters, VmCreate, VmDelete, VmInfo,
+ VmPause, VmPowerButton, VmReboot, VmReceiveMigration, VmRemoveDevice, VmResize, VmResizeZone,
+ VmRestore, VmResume, VmSendMigration, VmShutdown, VmSnapshot, VmmPing, VmmShutdown,
+@@ -154,6 +154,11 @@ impl DBusApi {
+ .await
}
+ async fn vm_add_gpu(&self, gpu_config: String) -> Result<Optional<String>> {
@@ -803,54 +811,42 @@ index 6f75fb5cd..78275925d 100644
let mut net_config: NetConfig = serde_json::from_str(&net_config).map_err(api_error)?;
if net_config.fds.is_some() {
diff --git a/vmm/src/api/http/http_endpoint.rs b/vmm/src/api/http/http_endpoint.rs
-index e463a2081..0936eff22 100644
+index 92b53ac..0e67daf 100644
--- a/vmm/src/api/http/http_endpoint.rs
+++ b/vmm/src/api/http/http_endpoint.rs
-@@ -45,10 +45,10 @@ use crate::api::VmCoredump;
+@@ -45,7 +45,7 @@ use crate::api::VmCoredump;
use crate::api::http::http_endpoint::fds_helper::{attach_fds_to_cfg, attach_fds_to_cfgs};
use crate::api::http::{EndpointHandler, HttpError, error_response};
use crate::api::{
-- AddDisk, ApiAction, ApiError, ApiRequest, NetConfig, VmAddDevice, VmAddFs, VmAddNet, VmAddPmem,
-- VmAddUserDevice, VmAddVdpa, VmAddVsock, VmBoot, VmConfig, VmCounters, VmDelete, VmNmi, VmPause,
-- VmPowerButton, VmReboot, VmReceiveMigration, VmRemoveDevice, VmResize, VmResizeDisk,
-- VmResizeZone, VmRestore, VmResume, VmSendMigration, VmShutdown, VmSnapshot,
-+ AddDisk, ApiAction, ApiError, ApiRequest, NetConfig, VmAddDevice, VmAddFs, VmAddGpu, VmAddNet,
-+ VmAddPmem, VmAddUserDevice, VmAddVdpa, VmAddVsock, VmBoot, VmConfig, VmCounters, VmDelete,
-+ VmNmi, VmPause, VmPowerButton, VmReboot, VmReceiveMigration, VmRemoveDevice, VmResize,
-+ VmResizeDisk, VmResizeZone, VmRestore, VmResume, VmSendMigration, VmShutdown, VmSnapshot,
- };
- use crate::config::RestoreConfig;
- use crate::cpu::Error as CpuError;
-@@ -419,6 +419,7 @@ vm_action_put_handler!(VmNmi);
- vm_action_put_handler_body!(VmAddDevice);
+- AddDisk, ApiAction, ApiError, ApiRequest, NetConfig, VmAddDevice, VmAddFs,
++ AddDisk, ApiAction, ApiError, ApiRequest, NetConfig, VmAddDevice, VmAddFs, VmAddGpu,
+ VmAddGenericVhostUser, VmAddNet, VmAddPmem, VmAddUserDevice, VmAddVdpa, VmAddVsock, VmBoot,
+ VmConfig, VmCounters, VmDelete, VmNmi, VmPause, VmPowerButton, VmReboot, VmReceiveMigration,
+ VmRemoveDevice, VmResize, VmResizeDisk, VmResizeZone, VmRestore, VmResume, VmSendMigration,
+@@ -421,6 +421,7 @@ vm_action_put_handler_body!(VmAddDevice);
vm_action_put_handler_body!(AddDisk);
vm_action_put_handler_body!(VmAddFs);
+ vm_action_put_handler_body!(VmAddGenericVhostUser);
+vm_action_put_handler_body!(VmAddGpu);
vm_action_put_handler_body!(VmAddPmem);
vm_action_put_handler_body!(VmAddVdpa);
vm_action_put_handler_body!(VmAddVsock);
diff --git a/vmm/src/api/http/mod.rs b/vmm/src/api/http/mod.rs
-index 2aa52e8e3..7eccb57d1 100644
+index f7cea4f..bd71ce9 100644
--- a/vmm/src/api/http/mod.rs
+++ b/vmm/src/api/http/mod.rs
-@@ -28,10 +28,10 @@ use self::http_endpoint::{VmActionHandler, VmCreate, VmInfo, VmmPing, VmmShutdow
+@@ -28,7 +28,7 @@ use self::http_endpoint::{VmActionHandler, VmCreate, VmInfo, VmmPing, VmmShutdow
#[cfg(all(target_arch = "x86_64", feature = "guest_debug"))]
use crate::api::VmCoredump;
use crate::api::{
-- AddDisk, ApiError, ApiRequest, VmAddDevice, VmAddFs, VmAddNet, VmAddPmem, VmAddUserDevice,
-- VmAddVdpa, VmAddVsock, VmBoot, VmCounters, VmDelete, VmNmi, VmPause, VmPowerButton, VmReboot,
-- VmReceiveMigration, VmRemoveDevice, VmResize, VmResizeDisk, VmResizeZone, VmRestore, VmResume,
-- VmSendMigration, VmShutdown, VmSnapshot,
-+ AddDisk, ApiError, ApiRequest, VmAddDevice, VmAddFs, VmAddGpu, VmAddNet, VmAddPmem,
-+ VmAddUserDevice, VmAddVdpa, VmAddVsock, VmBoot, VmCounters, VmDelete, VmNmi, VmPause,
-+ VmPowerButton, VmReboot, VmReceiveMigration, VmRemoveDevice, VmResize, VmResizeDisk,
-+ VmResizeZone, VmRestore, VmResume, VmSendMigration, VmShutdown, VmSnapshot,
- };
- use crate::landlock::Landlock;
- use crate::seccomp_filters::{Thread, get_seccomp_filter};
-@@ -196,6 +196,10 @@ pub static HTTP_ROUTES: LazyLock<HttpRoutes> = LazyLock::new(|| {
- endpoint!("/vm.add-fs"),
- Box::new(VmActionHandler::new(&VmAddFs)),
+- AddDisk, ApiError, ApiRequest, VmAddDevice, VmAddFs, VmAddGenericVhostUser, VmAddNet,
++ AddDisk, ApiError, ApiRequest, VmAddDevice, VmAddFs, VmAddGenericVhostUser, VmAddGpu, VmAddNet,
+ VmAddPmem, VmAddUserDevice, VmAddVdpa, VmAddVsock, VmBoot, VmCounters, VmDelete, VmNmi,
+ VmPause, VmPowerButton, VmReboot, VmReceiveMigration, VmRemoveDevice, VmResize, VmResizeDisk,
+ VmResizeZone, VmRestore, VmResume, VmSendMigration, VmShutdown, VmSnapshot,
+@@ -202,6 +202,10 @@ pub static HTTP_ROUTES: LazyLock<HttpRoutes> = LazyLock::new(|| {
+ endpoint!("/vm.add-generic-vhost-user"),
+ Box::new(VmActionHandler::new(&VmAddGenericVhostUser)),
);
+ r.routes.insert(
+ endpoint!("/vm.add-gpu"),
@@ -860,41 +856,39 @@ index 2aa52e8e3..7eccb57d1 100644
endpoint!("/vm.add-net"),
Box::new(VmActionHandler::new(&VmAddNet)),
diff --git a/vmm/src/api/mod.rs b/vmm/src/api/mod.rs
-index 12ca6b987..aaafe3843 100644
+index e4ee723..8f8052e 100644
--- a/vmm/src/api/mod.rs
+++ b/vmm/src/api/mod.rs
-@@ -51,8 +51,8 @@ use crate::config::RestoreConfig;
- use crate::device_tree::DeviceTree;
+@@ -56,7 +56,7 @@ use crate::device_tree::DeviceTree;
+ use crate::migration_transport::MAX_MIGRATION_CONNECTIONS;
use crate::vm::{Error as VmError, VmState};
use crate::vm_config::{
-- DeviceConfig, DiskConfig, FsConfig, NetConfig, PmemConfig, UserDeviceConfig, VdpaConfig,
-- VmConfig, VsockConfig,
-+ DeviceConfig, DiskConfig, FsConfig, GpuConfig, NetConfig, PmemConfig, UserDeviceConfig,
-+ VdpaConfig, VmConfig, VsockConfig,
+- DeviceConfig, DiskConfig, FsConfig, GenericVhostUserConfig, NetConfig, PmemConfig,
++ DeviceConfig, DiskConfig, FsConfig, GenericVhostUserConfig, GpuConfig, NetConfig, PmemConfig,
+ UserDeviceConfig, VdpaConfig, VmConfig, VsockConfig,
};
- /// API errors are sent back from the VMM API server through the ApiResponse.
-@@ -170,6 +170,10 @@ pub enum ApiError {
- #[error("The fs could not be added to the VM")]
- VmAddFs(#[source] VmError),
+@@ -179,6 +179,10 @@ pub enum ApiError {
+ #[error("The generic vhost-user device could not be added to the VM")]
+ VmAddGenericVhostUser(#[source] VmError),
-+ /// The gpu could not be added to the VM.
-+ #[error("The GPU could not be added to the VM: {0}")]
++ /// The gpu device could not be added to the VM.
++ #[error("The gpu device could not be added to the VM")]
+ VmAddGpu(#[source] VmError),
+
/// The pmem device could not be added to the VM.
#[error("The pmem device could not be added to the VM")]
VmAddPmem(#[source] VmError),
-@@ -340,6 +344,8 @@ pub trait RequestHandler {
-
- fn vm_add_fs(&mut self, fs_cfg: FsConfig) -> Result<Option<Vec<u8>>, VmError>;
+@@ -561,6 +565,8 @@ pub trait RequestHandler {
+ fs_cfg: GenericVhostUserConfig,
+ ) -> Result<Option<Vec<u8>>, VmError>;
+ fn vm_add_gpu(&mut self, gpu_cfg: GpuConfig) -> Result<Option<Vec<u8>>, VmError>;
+
fn vm_add_pmem(&mut self, pmem_cfg: PmemConfig) -> Result<Option<Vec<u8>>, VmError>;
fn vm_add_net(&mut self, net_cfg: NetConfig) -> Result<Option<Vec<u8>>, VmError>;
-@@ -539,6 +545,43 @@ impl ApiAction for VmAddFs {
+@@ -797,6 +803,43 @@ impl ApiAction for VmAddGenericVhostUser {
}
}
@@ -939,10 +933,10 @@ index 12ca6b987..aaafe3843 100644
impl ApiAction for VmAddPmem {
diff --git a/vmm/src/api/openapi/cloud-hypervisor.yaml b/vmm/src/api/openapi/cloud-hypervisor.yaml
-index 1fa3d9b51..cc290e27f 100644
+index e8b72f7..5c01292 100644
--- a/vmm/src/api/openapi/cloud-hypervisor.yaml
+++ b/vmm/src/api/openapi/cloud-hypervisor.yaml
-@@ -277,6 +277,28 @@ paths:
+@@ -299,6 +299,28 @@ paths:
500:
description: The new device could not be added to the VM instance.
@@ -971,7 +965,7 @@ index 1fa3d9b51..cc290e27f 100644
/vm.add-pmem:
put:
summary: Add a new pmem device to the VM
-@@ -603,6 +625,10 @@ components:
+@@ -629,6 +651,10 @@ components:
type: array
items:
$ref: "#/components/schemas/FsConfig"
@@ -979,12 +973,12 @@ index 1fa3d9b51..cc290e27f 100644
+ type: array
+ items:
+ $ref: "#/components/schemas/GpuConfig"
- pmem:
+ generic-vhost-user:
type: array
items:
-@@ -1044,6 +1070,19 @@ components:
- id:
- type: string
+@@ -1154,6 +1180,22 @@ components:
+ virtio_id:
+ type: uint32
+ GpuConfig:
+ required:
@@ -993,50 +987,46 @@ index 1fa3d9b51..cc290e27f 100644
+ properties:
+ socket:
+ type: string
++ id:
++ type: string
+ pci_segment:
+ type: integer
+ format: int16
-+ id:
-+ type: string
++ pci_device_id:
++ type: integer
++ format: uint8
+
PmemConfig:
required:
- file
diff --git a/vmm/src/config.rs b/vmm/src/config.rs
-index 78d6f9f1e..e1a54b0fa 100644
+index 00bf251..906410b 100644
--- a/vmm/src/config.rs
+++ b/vmm/src/config.rs
-@@ -45,6 +45,9 @@ pub enum Error {
- /// Filesystem socket is missing
- #[error("Error parsing --fs: socket missing")]
- ParseFsSockMissing,
-+ /// GPU socket is missing
-+ #[error("Error parsing --gpu: socket missing")]
-+ ParseGpuSockMissing,
- /// Missing persistent memory file parameter.
- #[error("Error parsing --pmem: file missing")]
- ParsePmemFileMissing,
-@@ -90,6 +93,9 @@ pub enum Error {
+@@ -122,6 +122,12 @@ pub enum Error {
/// Error parsing filesystem parameters
#[error("Error parsing --fs")]
ParseFileSystem(#[source] OptionParserError),
+ /// Error parsing GPU parameters
+ #[error("Error parsing --gpu")]
+ ParseGpu(#[source] OptionParserError),
++ /// GPU socket is missing
++ #[error("Error parsing --gpu: socket missing")]
++ ParseGpuSockMissing,
/// Error parsing persistent memory parameters
#[error("Error parsing --pmem")]
ParsePersistentMemory(#[source] OptionParserError),
-@@ -390,6 +396,7 @@ pub struct VmParams<'a> {
- pub rng: &'a str,
+@@ -460,6 +466,7 @@ pub struct VmParams<'a> {
pub balloon: Option<&'a str>,
pub fs: Option<Vec<&'a str>>,
+ pub generic_vhost_user: Option<Vec<&'a str>>,
+ pub gpu: Option<Vec<&'a str>>,
pub pmem: Option<Vec<&'a str>>,
pub serial: &'a str,
pub console: &'a str,
-@@ -451,6 +458,9 @@ impl<'a> VmParams<'a> {
- let fs: Option<Vec<&str>> = args
- .get_many::<String>("fs")
+@@ -524,6 +531,9 @@ impl<'a> VmParams<'a> {
+ let generic_vhost_user: Option<Vec<&str>> = args
+ .get_many::<String>("generic-vhost-user")
.map(|x| x.map(|y| y as &str).collect());
+ let gpu: Option<Vec<&str>> = args
+ .get_many::<String>("gpu")
@@ -1044,65 +1034,45 @@ index 78d6f9f1e..e1a54b0fa 100644
let pmem: Option<Vec<&str>> = args
.get_many::<String>("pmem")
.map(|x| x.map(|y| y as &str).collect());
-@@ -505,6 +515,7 @@ impl<'a> VmParams<'a> {
- rng,
+@@ -579,6 +589,7 @@ impl<'a> VmParams<'a> {
balloon,
fs,
+ generic_vhost_user,
+ gpu,
pmem,
serial,
console,
-@@ -1766,6 +1777,49 @@ impl FwCfgItem {
+@@ -2100,6 +2111,29 @@ impl FwCfgItem {
}
}
+impl GpuConfig {
+ pub const SYNTAX: &'static str = "virtio-gpu parameters \
-+ \"socket=<socket_path>,id=<device_id>,pci_segment=<segment_id>\"";
++ \"socket=<socket_path>,id=<device_id>,pci_segment=<segment_id>,pci_device_id=<pci_slot>\"";
+
+ pub fn parse(gpu: &str) -> Result<Self> {
+ let mut parser = OptionParser::new();
-+ parser.add("socket").add("id").add("pci_segment");
++ parser.add("socket").add_all(PciDeviceCommonConfig::OPTIONS);
+ parser.parse(gpu).map_err(Error::ParseGpu)?;
+
++ let pci_common = PciDeviceCommonConfig::parse(gpu)?;
+ let socket = PathBuf::from(parser.get("socket").ok_or(Error::ParseGpuSockMissing)?);
-+ let id = parser.get("id");
+
-+ let pci_segment = parser
-+ .convert("pci_segment")
-+ .map_err(Error::ParseGpu)?
-+ .unwrap_or_default();
-+
-+ Ok(GpuConfig {
-+ socket,
-+ id,
-+ pci_segment,
-+ })
++ Ok(GpuConfig { pci_common, socket })
+ }
+
+ pub fn validate(&self, vm_config: &VmConfig) -> ValidationResult<()> {
-+ if let Some(platform_config) = vm_config.platform.as_ref() {
-+ if self.pci_segment >= platform_config.num_pci_segments {
-+ return Err(ValidationError::InvalidPciSegment(self.pci_segment));
-+ }
-+
-+ if let Some(iommu_segments) = platform_config.iommu_segments.as_ref()
-+ && iommu_segments.contains(&self.pci_segment)
-+ {
-+ return Err(ValidationError::IommuNotSupportedOnSegment(
-+ self.pci_segment,
-+ ));
-+ }
++ if self.pci_common.iommu {
++ return Err(ValidationError::IommuUnsupported);
+ }
-+
-+ Ok(())
++ self.pci_common.validate(vm_config)
+ }
+}
+
impl PmemConfig {
pub const SYNTAX: &'static str = "Persistent memory parameters \
\"file=<backing_file_path>,size=<persistent_memory_size>,iommu=on|off,\
-@@ -2624,6 +2678,17 @@ impl VmConfig {
+@@ -3041,6 +3075,17 @@ impl VmConfig {
}
}
@@ -1113,15 +1083,15 @@ index 78d6f9f1e..e1a54b0fa 100644
+ for gpu in gpus {
+ gpu.validate(self)?;
+
-+ Self::validate_identifier(&mut id_list, &gpu.id)?;
++ Self::validate_identifier(&mut id_list, &gpu.pci_common.id)?;
+ }
+ }
+
if let Some(pmems) = &self.pmem {
for pmem in pmems {
pmem.validate(self)?;
-@@ -2876,6 +2941,15 @@ impl VmConfig {
- fs = Some(fs_config_list);
+@@ -3318,6 +3363,15 @@ impl VmConfig {
+ generic_vhost_user = Some(generic_vhost_user_config_list);
}
+ let mut gpu: Option<Vec<GpuConfig>> = None;
@@ -1136,77 +1106,53 @@ index 78d6f9f1e..e1a54b0fa 100644
let mut pmem: Option<Vec<PmemConfig>> = None;
if let Some(pmem_list) = &vm_params.pmem {
let mut pmem_config_list = Vec::new();
-@@ -3012,6 +3086,7 @@ impl VmConfig {
- rng,
+@@ -3455,6 +3509,7 @@ impl VmConfig {
balloon,
+ generic_vhost_user,
fs,
+ gpu,
pmem,
serial,
console,
-@@ -3073,6 +3148,13 @@ impl VmConfig {
- removed |= fs.len() != len;
+@@ -3524,6 +3579,13 @@ impl VmConfig {
+ removed |= generic_vhost_user.len() != len;
}
+ // Remove if gpu device
+ if let Some(gpu) = self.gpu.as_mut() {
+ let len = gpu.len();
-+ gpu.retain(|dev| dev.id.as_ref().map(|id| id.as_ref()) != Some(id));
++ gpu.retain(|dev| dev.pci_common.id.as_ref().map(|id| id.as_ref()) != Some(id));
+ removed |= gpu.len() != len;
+ }
+
// Remove if net device
if let Some(net) = self.net.as_mut() {
let len = net.len();
-@@ -3145,6 +3227,7 @@ impl Clone for VmConfig {
- #[cfg(feature = "pvmemcontrol")]
+@@ -3597,6 +3659,7 @@ impl Clone for VmConfig {
pvmemcontrol: self.pvmemcontrol.clone(),
fs: self.fs.clone(),
+ generic_vhost_user: self.generic_vhost_user.clone(),
+ gpu: self.gpu.clone(),
pmem: self.pmem.clone(),
serial: self.serial.clone(),
console: self.console.clone(),
-@@ -3665,6 +3748,23 @@ mod unit_tests {
- Ok(())
- }
-
-+ fn gpu_fixture() -> GpuConfig {
-+ GpuConfig {
-+ socket: PathBuf::from("/tmp/sock"),
-+ id: None,
-+ pci_segment: 0,
-+ }
-+ }
-+
-+ #[test]
-+ fn test_parse_gpu() -> Result<()> {
-+ // "socket" must be supplied
-+ assert!(GpuConfig::parse("").is_err());
-+ assert_eq!(GpuConfig::parse("socket=/tmp/sock")?, gpu_fixture());
-+
-+ Ok(())
-+ }
-+
- fn pmem_fixture() -> PmemConfig {
- PmemConfig {
- file: PathBuf::from("/tmp/pmem"),
-@@ -3936,6 +4036,7 @@ mod unit_tests {
- rng: RngConfig::default(),
+@@ -4811,6 +4874,7 @@ id=\"{id}\",pci_segment={pci_segment},queue_sizes={queue_sizes}"
+ generic_vhost_user: None,
balloon: None,
fs: None,
+ gpu: None,
pmem: None,
- serial: default_serial(),
- console: default_console(),
-@@ -4138,6 +4239,7 @@ mod unit_tests {
- },
+ serial: SerialConfig::default(),
+ console: ConsoleConfig::default(),
+@@ -5045,6 +5109,7 @@ id=\"{id}\",pci_segment={pci_segment},queue_sizes={queue_sizes}"
balloon: None,
fs: None,
+ generic_vhost_user: None,
+ gpu: None,
pmem: None,
- serial: ConsoleConfig {
- file: None,
-@@ -4334,6 +4436,13 @@ mod unit_tests {
+ serial: SerialConfig {
+ common: CommonConsoleConfig {
+@@ -5354,6 +5419,13 @@ id=\"{id}\",pci_segment={pci_segment},queue_sizes={queue_sizes}"
Err(ValidationError::VhostUserRequiresSharedMemory)
);
@@ -1221,7 +1167,7 @@ index 78d6f9f1e..e1a54b0fa 100644
still_valid_config.memory.shared = true;
still_valid_config.validate().unwrap();
diff --git a/vmm/src/device_manager.rs b/vmm/src/device_manager.rs
-index 6d465047b..7eb1358e1 100644
+index e6902a4..4329af3 100644
--- a/vmm/src/device_manager.rs
+++ b/vmm/src/device_manager.rs
@@ -12,6 +12,7 @@
@@ -1232,40 +1178,41 @@ index 6d465047b..7eb1358e1 100644
use std::num::Wrapping;
use std::os::unix::fs::OpenOptionsExt;
use std::os::unix::io::{AsRawFd, FromRawFd};
-@@ -91,7 +92,7 @@ use virtio_devices::transport::{VirtioPciDevice, VirtioPciDeviceActivator, Virti
+@@ -89,7 +90,7 @@ use virtio_devices::transport::{VirtioPciDevice, VirtioPciDeviceActivator, Virti
use virtio_devices::vhost_user::VhostUserConfig;
use virtio_devices::{
AccessPlatformMapping, ActivateError, Block, Endpoint, IommuMapping, VdpaDmaMapping,
- VirtioMemMappingSource,
+ VirtioMemMappingSource, VirtioSharedMemory, VirtioSharedMemoryList,
};
- use vm_allocator::{AddressAllocator, SystemAllocator};
+ use vm_allocator::{AddressAllocator, InterruptAllocError, SystemAllocator};
use vm_device::dma_mapping::ExternalDmaMapping;
-@@ -124,8 +125,8 @@ use crate::serial_manager::{Error as SerialManagerError, SerialManager};
+@@ -122,8 +123,9 @@ use crate::serial_manager::{Error as SerialManagerError, SerialManager};
use crate::vm_config::IvshmemConfig;
use crate::vm_config::{
ConsoleOutputMode, DEFAULT_IOMMU_ADDRESS_WIDTH_BITS, DEFAULT_PCI_SEGMENT_APERTURE_WEIGHT,
-- DeviceConfig, DiskConfig, FsConfig, NetConfig, PmemConfig, UserDeviceConfig, VdpaConfig,
-- VhostMode, VmConfig, VsockConfig,
-+ DeviceConfig, DiskConfig, FsConfig, GpuConfig, NetConfig, PmemConfig, UserDeviceConfig,
-+ VdpaConfig, VhostMode, VmConfig, VsockConfig,
+- DeviceConfig, DiskConfig, FsConfig, GenericVhostUserConfig, NetConfig, PciDeviceCommonConfig,
+- PmemConfig, UserDeviceConfig, VdpaConfig, VhostMode, VmConfig, VsockConfig,
++ DeviceConfig, DiskConfig, FsConfig, GenericVhostUserConfig, GpuConfig, NetConfig,
++ PciDeviceCommonConfig, PmemConfig, UserDeviceConfig, VdpaConfig, VhostMode, VmConfig,
++ VsockConfig,
};
use crate::{DEVICE_MANAGER_SNAPSHOT_ID, GuestRegionMmap, PciDeviceInfo, device_node};
-@@ -154,6 +155,7 @@ const IVSHMEM_DEVICE_NAME: &str = "__ivshmem";
- // identifiers if the user doesn't give one
- const DISK_DEVICE_NAME_PREFIX: &str = "_disk";
+@@ -154,6 +156,7 @@ const DISK_DEVICE_NAME_PREFIX: &str = "_disk";
const FS_DEVICE_NAME_PREFIX: &str = "_fs";
-+const GPU_DEVICE_NAME_PREFIX: &str = "_gpu";
const NET_DEVICE_NAME_PREFIX: &str = "_net";
+ const GENERIC_VHOST_USER_DEVICE_NAME_PREFIX: &str = "_generic_vhost_user";
++const GPU_DEVICE_NAME_PREFIX: &str = "_gpu";
const PMEM_DEVICE_NAME_PREFIX: &str = "_pmem";
const VDPA_DEVICE_NAME_PREFIX: &str = "_vdpa";
-@@ -198,10 +200,18 @@ pub enum DeviceManagerError {
+ const VSOCK_DEVICE_NAME_PREFIX: &str = "_vsock";
+@@ -201,10 +204,18 @@ pub enum DeviceManagerError {
#[error("Cannot create virtio-fs device")]
CreateVirtioFs(#[source] virtio_devices::vhost_user::Error),
+ /// Cannot create virtio-gpu device
-+ #[error("Cannot create virtio-gpu device: {0}")]
++ #[error("Cannot create virtio-gpu device")]
+ CreateVirtioGpu(#[source] virtio_devices::vhost_user::Error),
+
/// Virtio-fs device was created without a socket.
@@ -1276,10 +1223,10 @@ index 6d465047b..7eb1358e1 100644
+ #[error("Virtio-gpu device was created without a socket")]
+ NoVirtioGpuSock,
+
- /// Cannot create vhost-user-blk device
- #[error("Cannot create vhost-user-blk device")]
- CreateVhostUserBlk(#[source] virtio_devices::vhost_user::Error),
-@@ -319,6 +329,10 @@ pub enum DeviceManagerError {
+ /// Generic vhost-user device was created without a socket.
+ #[error("Generic vhost-user device was created without a socket")]
+ NoGenericVhostUserSock,
+@@ -318,6 +329,10 @@ pub enum DeviceManagerError {
#[error("Cannot find a memory range for virtio-fs")]
FsRangeAllocation,
@@ -1290,7 +1237,7 @@ index 6d465047b..7eb1358e1 100644
/// Error creating serial output file
#[error("Error creating serial output file")]
SerialOutputFileOpen(#[source] io::Error),
-@@ -2537,6 +2551,9 @@ impl DeviceManager {
+@@ -2630,6 +2645,9 @@ impl DeviceManager {
// Add virtio-fs if required
self.make_virtio_fs_devices()?;
@@ -1300,7 +1247,7 @@ index 6d465047b..7eb1358e1 100644
// Add virtio-pmem if required
self.make_virtio_pmem_devices()?;
-@@ -3117,6 +3134,119 @@ impl DeviceManager {
+@@ -3234,6 +3252,121 @@ impl DeviceManager {
Ok(())
}
@@ -1308,12 +1255,13 @@ index 6d465047b..7eb1358e1 100644
+ &mut self,
+ gpu_cfg: &mut GpuConfig,
+ ) -> DeviceManagerResult<MetaVirtioDevice> {
-+ let id = if let Some(id) = &gpu_cfg.id {
-+ id.clone()
-+ } else {
-+ let id = self.next_device_name(GPU_DEVICE_NAME_PREFIX)?;
-+ gpu_cfg.id = Some(id.clone());
-+ id
++ let id = match gpu_cfg.pci_common.id.as_ref() {
++ Some(id) => id.clone(),
++ None => gpu_cfg
++ .pci_common
++ .id
++ .insert(self.next_device_name(GPU_DEVICE_NAME_PREFIX)?)
++ .clone(),
+ };
+
+ info!("Creating virtio-gpu device: {gpu_cfg:?}");
@@ -1321,35 +1269,38 @@ index 6d465047b..7eb1358e1 100644
+ let mut node = device_node!(id);
+
+ if let Some(gpu_socket) = gpu_cfg.socket.to_str() {
-+ let (mut virtio_gpu_device, region) = virtio_devices::vhost_user::Gpu::new(
++ let (mut virtio_gpu_device, shmem_config) = virtio_devices::vhost_user::Gpu::new(
+ id.clone(),
+ gpu_socket,
+ self.seccomp_action.clone(),
+ self.exit_evt
+ .try_clone()
+ .map_err(DeviceManagerError::EventFd)?,
-+ self.force_iommu,
++ self.force_access_platform | gpu_cfg.pci_common.iommu,
+ )
+ .map_err(DeviceManagerError::CreateVirtioGpu)?;
+
++ let shm_id = 0;
++ let shm_len = shmem_config.memory_sizes[shm_id as usize];
++
+ // In crosvm, the 8 GiB bar is 8 GiB-aligned.
-+ let cache_base = self.pci_segments[gpu_cfg.pci_segment as usize]
++ let cache_base = self.pci_segments[gpu_cfg.pci_common.pci_segment as usize]
+ .mem64_allocator
+ .lock()
+ .unwrap()
-+ .allocate(None, region.length as GuestUsize, Some(region.length))
++ .allocate(None, shm_len as GuestUsize, Some(shm_len))
+ .ok_or(DeviceManagerError::GpuRangeAllocation)?
+ .raw_value();
+
+ // Update the node with correct resource information.
+ node.resources.push(Resource::MmioAddressRange {
+ base: cache_base,
-+ size: region.length,
++ size: shm_len,
+ });
+
+ let mmap_region = MmapRegion::build(
+ None,
-+ region.length as usize,
++ shm_len as usize,
+ libc::PROT_NONE,
+ libc::MAP_ANONYMOUS | libc::MAP_PRIVATE,
+ )
@@ -1374,10 +1325,10 @@ index 6d465047b..7eb1358e1 100644
+ };
+
+ let region_list = once((
-+ region.id,
++ shm_id,
+ VirtioSharedMemory {
+ offset: 0,
-+ len: region.length,
++ len: shm_len,
+ },
+ ))
+ .collect();
@@ -1394,9 +1345,7 @@ index 6d465047b..7eb1358e1 100644
+ Ok(MetaVirtioDevice {
+ virtio_device: Arc::new(Mutex::new(virtio_gpu_device))
+ as Arc<Mutex<dyn virtio_devices::VirtioDevice>>,
-+ iommu: false,
-+ id,
-+ pci_segment: gpu_cfg.pci_segment,
++ pci_common: gpu_cfg.pci_common.clone(),
+ dma_handler: None,
+ })
+ } else {
@@ -1420,7 +1369,7 @@ index 6d465047b..7eb1358e1 100644
fn make_virtio_pmem_device(
&mut self,
pmem_cfg: &mut PmemConfig,
-@@ -4541,6 +4671,7 @@ impl DeviceManager {
+@@ -4765,6 +4898,7 @@ impl DeviceManager {
VirtioDeviceType::Block
| VirtioDeviceType::Pmem
| VirtioDeviceType::Fs
@@ -1428,36 +1377,34 @@ index 6d465047b..7eb1358e1 100644
| VirtioDeviceType::Vsock => {}
_ => return Err(DeviceManagerError::RemovalNotAllowed(device_type)),
}
-@@ -4827,6 +4958,13 @@ impl DeviceManager {
+@@ -5086,6 +5220,13 @@ impl DeviceManager {
self.hotplug_virtio_pci_device(device)
}
+ pub fn add_gpu(&mut self, gpu_cfg: &mut GpuConfig) -> DeviceManagerResult<PciDeviceInfo> {
-+ self.validate_identifier(&gpu_cfg.id)?;
++ self.validate_identifier(&gpu_cfg.pci_common.id)?;
+
+ let device = self.make_virtio_gpu_device(gpu_cfg)?;
+ self.hotplug_virtio_pci_device(device)
+ }
+
pub fn add_pmem(&mut self, pmem_cfg: &mut PmemConfig) -> DeviceManagerResult<PciDeviceInfo> {
- self.validate_identifier(&pmem_cfg.id)?;
+ self.validate_identifier(&pmem_cfg.pci_common.id)?;
diff --git a/vmm/src/lib.rs b/vmm/src/lib.rs
-index 6917e005e..5a3db353a 100644
+index 6c9d476..d0e1c33 100644
--- a/vmm/src/lib.rs
+++ b/vmm/src/lib.rs
-@@ -59,8 +59,8 @@ use crate::migration::{recv_vm_config, recv_vm_state};
+@@ -65,7 +65,7 @@ use crate::migration_transport::{
use crate::seccomp_filters::{Thread, get_seccomp_filter};
use crate::vm::{Error as VmError, Vm, VmState};
use crate::vm_config::{
-- DeviceConfig, DiskConfig, FsConfig, NetConfig, PmemConfig, UserDeviceConfig, VdpaConfig,
-- VmConfig, VsockConfig,
-+ DeviceConfig, DiskConfig, FsConfig, GpuConfig, NetConfig, PmemConfig, UserDeviceConfig,
-+ VdpaConfig, VmConfig, VsockConfig,
+- DeviceConfig, DiskConfig, FsConfig, GenericVhostUserConfig, NetConfig, PmemConfig,
++ DeviceConfig, DiskConfig, FsConfig, GenericVhostUserConfig, GpuConfig, NetConfig, PmemConfig,
+ UserDeviceConfig, VdpaConfig, VmConfig, VsockConfig,
};
- mod acpi;
-@@ -2120,6 +2120,31 @@ impl RequestHandler for Vmm {
+@@ -2365,6 +2365,31 @@ impl RequestHandler for Vmm {
}
}
@@ -1489,15 +1436,15 @@ index 6917e005e..5a3db353a 100644
fn vm_add_pmem(&mut self, pmem_cfg: PmemConfig) -> result::Result<Option<Vec<u8>>, VmError> {
self.vm_config.as_ref().ok_or(VmError::VmNotCreated)?;
-@@ -2438,6 +2463,7 @@ mod unit_tests {
- },
+@@ -2722,6 +2747,7 @@ mod unit_tests {
balloon: None,
fs: None,
+ generic_vhost_user: None,
+ gpu: None,
pmem: None,
- serial: ConsoleConfig {
- file: None,
-@@ -2674,6 +2700,55 @@ mod unit_tests {
+ serial: SerialConfig {
+ common: CommonConsoleConfig {
+@@ -3014,6 +3040,55 @@ mod unit_tests {
);
}
@@ -1554,21 +1501,19 @@ index 6917e005e..5a3db353a 100644
fn test_vmm_vm_cold_add_pmem() {
let mut vmm = create_dummy_vmm();
diff --git a/vmm/src/vm.rs b/vmm/src/vm.rs
-index 536481885..d2e5de0fe 100644
+index 1c3baf8..ae5a2e8 100644
--- a/vmm/src/vm.rs
+++ b/vmm/src/vm.rs
-@@ -100,8 +100,8 @@ use crate::migration::{SNAPSHOT_CONFIG_FILE, SNAPSHOT_STATE_FILE, url_to_path};
+@@ -115,7 +115,7 @@ use crate::sev::MeasuredBootInfo;
#[cfg(feature = "fw_cfg")]
use crate::vm_config::FwCfgConfig;
use crate::vm_config::{
-- DeviceConfig, DiskConfig, FsConfig, HotplugMethod, NetConfig, NumaConfig, PayloadConfig,
-- PmemConfig, UserDeviceConfig, VdpaConfig, VmConfig, VsockConfig,
-+ DeviceConfig, DiskConfig, FsConfig, GpuConfig, HotplugMethod, NetConfig, NumaConfig,
-+ PayloadConfig, PmemConfig, UserDeviceConfig, VdpaConfig, VmConfig, VsockConfig,
+- DeviceConfig, DiskConfig, FsConfig, GenericVhostUserConfig, HotplugMethod, NetConfig,
++ DeviceConfig, DiskConfig, FsConfig, GenericVhostUserConfig, GpuConfig, HotplugMethod, NetConfig,
+ NumaConfig, PayloadConfig, PmemConfig, UserDeviceConfig, VdpaConfig, VmConfig, VsockConfig,
};
use crate::{
- CPU_MANAGER_SNAPSHOT_ID, DEVICE_MANAGER_SNAPSHOT_ID, GuestMemoryMmap,
-@@ -1869,6 +1869,30 @@ impl Vm {
+@@ -2348,6 +2348,30 @@ impl Vm {
Ok(pci_device_info)
}
@@ -1600,33 +1545,30 @@ index 536481885..d2e5de0fe 100644
let pci_device_info = self
.device_manager
diff --git a/vmm/src/vm_config.rs b/vmm/src/vm_config.rs
-index 9c28e536d..f21974ac2 100644
+index 6fefc8f..3834d1e 100644
--- a/vmm/src/vm_config.rs
+++ b/vmm/src/vm_config.rs
-@@ -461,6 +461,15 @@ impl ApplyLandlock for FsConfig {
- }
+@@ -485,6 +485,13 @@ pub struct FsConfig {
+ pub queue_size: u16,
}
+#[derive(Clone, Debug, PartialEq, Eq, Deserialize, Serialize)]
+pub struct GpuConfig {
++ #[serde(flatten)]
++ pub pci_common: PciDeviceCommonConfig,
+ pub socket: PathBuf,
-+ #[serde(default)]
-+ pub id: Option<String>,
-+ #[serde(default)]
-+ pub pci_segment: u16,
+}
+
- #[derive(Clone, Debug, PartialEq, Eq, Deserialize, Serialize)]
- pub struct PmemConfig {
- pub file: PathBuf,
-@@ -913,6 +922,7 @@ pub struct VmConfig {
- pub rng: RngConfig,
+ pub fn default_fsconfig_num_queues() -> usize {
+ 1
+ }
+@@ -1028,6 +1035,7 @@ pub struct VmConfig {
pub balloon: Option<BalloonConfig>,
+ pub generic_vhost_user: Option<Vec<GenericVhostUserConfig>>,
pub fs: Option<Vec<FsConfig>>,
+ pub gpu: Option<Vec<GpuConfig>>,
pub pmem: Option<Vec<PmemConfig>>,
- #[serde(default = "default_serial")]
- pub serial: ConsoleConfig,
+ #[serde(default)]
+ pub serial: SerialConfig,
--
-2.53.0
-
+2.54.0
diff --git a/pkgs/cloud-hypervisor/default.nix b/pkgs/cloud-hypervisor/default.nix
index ee5a7ea..e4ddb89 100644
--- a/pkgs/cloud-hypervisor/default.nix
+++ b/pkgs/cloud-hypervisor/default.nix
@@ -5,21 +5,77 @@
import ../../lib/overlay-package.nix [ "cloud-hypervisor" ] ({ final, super }:
super.cloud-hypervisor.overrideAttrs (oldAttrs: rec {
- cargoDeps = final.rustPlatform.fetchCargoVendor {
- inherit patches;
- inherit (oldAttrs) src;
- hash = "sha256-wGtsyKDg1z1QK9mJ1Q43NSjoPbm3m81p++DoD8ipIUI=";
+ version = "52.0";
+
+ src = final.fetchFromGitHub {
+ owner = "cloud-hypervisor";
+ repo = "cloud-hypervisor";
+ rev = "v${version}";
+ hash = "sha256-OGyvmedSaWPsyH6mdHhgXN7MvTnK1HzdfTKUhJRlq8I=";
+ };
+
+ cargoDeps = final.stdenvNoCC.mkDerivation {
+ name = "cloud-hypervisor-${version}-vendor";
+ inherit src patches vhost vhostPatches;
+
+ nativeBuildInputs = [
+ final.cacert
+ final.cargo
+ final.git
+ ];
+
+ outputHashMode = "recursive";
+ outputHashAlgo = "sha256";
+ outputHash = "sha256-DD0Mobe/mnsGb7xHKUFfdk/5VXvp8mZbfuRymtNvZLg=";
+ dontFixup = true;
+
+ postUnpack = ''
+ unpackFile $vhost
+ chmod -R +w vhost
+ '';
+
+ postPatch = ''
+ pushd ../vhost
+ for patch in $vhostPatches; do
+ echo applying patch $patch
+ patch -p1 < $patch
+ done
+ popd
+ '';
+
+ buildPhase = ''
+ runHook preBuild
+
+ export CARGO_HOME=$TMPDIR/cargo-home
+ mkdir -p .cargo
+ cargo vendor vendor > .cargo/config.toml
+ substituteInPlace .cargo/config.toml \
+ --replace-fail 'directory = "vendor"' 'directory = "@vendor@/vendor"'
+
+ runHook postBuild
+ '';
+
+ installPhase = ''
+ runHook preInstall
+
+ mkdir -p $out
+ cp Cargo.lock $out/Cargo.lock
+ cp -R vendor $out/vendor
+ cp -R .cargo $out/.cargo
+
+ runHook postInstall
+ '';
};
vhost = final.fetchFromGitHub {
name = "vhost";
owner = "rust-vmm";
repo = "vhost";
- rev = "vhost-user-backend-v0.20.0";
- hash = "sha256-KK1+mwYQr7YkyGT9+51v7TJael9D0lle2JXfRoTqYq8=";
+ rev = "vhost-user-backend-v0.22.0";
+ hash = "sha256-UzzwLi4O6rWuIJuGU0C0+tzJ7NZrgRamt/iYereRHZU=";
};
- patches = oldAttrs.patches or [] ++ [
+ patches = (oldAttrs.patches or []) ++ [
./0001-build-use-local-vhost.patch
./0002-virtio-devices-add-a-GPU-device.patch
];
@@ -27,16 +83,14 @@ super.cloud-hypervisor.overrideAttrs (oldAttrs: rec {
vhostPatches = [
vhost/0001-vhost_user-add-get_size-to-MsgHeader.patch
vhost/0002-vhost-fix-receiving-reply-payloads.patch
- vhost/0003-vhost_user-add-shared-memory-region-support.patch
- vhost/0004-vhost_user-add-protocol-flag-for-shmem.patch
];
- postUnpack = oldAttrs.postUnpack or "" + ''
+ postUnpack = (oldAttrs.postUnpack or "") + ''
unpackFile $vhost
chmod -R +w vhost
'';
- postPatch = oldAttrs.postPatch or "" + ''
+ postPatch = (oldAttrs.postPatch or "") + ''
pushd ../vhost
for patch in $vhostPatches; do
echo applying patch $patch
--
2.54.0
next prev parent reply other threads:[~2026-06-25 17:49 UTC|newest]
Thread overview: 16+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-06-25 17:48 [PATCH 0/6] cloud-hypervisor v52 and VM runtime fixes colbyt
2026-06-25 17:48 ` [PATCH 1/6] pkgs/skaware: vendor backported patches colbyt
2026-06-26 13:39 ` Alyssa Ross
2026-06-25 17:48 ` colbyt [this message]
2026-06-26 14:06 ` [PATCH 2/6] pkgs/cloud-hypervisor: update GPU patchset to v52 Alyssa Ross
2026-06-25 17:48 ` [PATCH 3/6] vm: use vhost-user networking for crosvm colbyt
2026-06-26 14:45 ` Alyssa Ross
2026-07-02 9:07 ` Alyssa Ross
2026-06-25 17:48 ` [PATCH 4/6] Documentation: use crosvm GPU socket-path option colbyt
2026-06-26 14:18 ` Alyssa Ross
2026-06-25 17:48 ` [PATCH 5/6] installer: suppress boot console status noise colbyt
2026-06-26 14:46 ` Alyssa Ross
2026-06-26 19:09 ` colby
2026-07-02 11:44 ` Alyssa Ross
2026-06-25 17:48 ` [PATCH 6/6] start-vmm: test GPU socket configuration colbyt
2026-06-26 14:18 ` Alyssa Ross
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=7cb1c12557f07e353186254250bfea29e36c8f30.1782409229.git.colby@colbyt.com \
--to=colby@colbyt.com \
--cc=devel@spectrum-os.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
Code repositories for project(s) associated with this public inbox
https://spectrum-os.org/git/crosvm
https://spectrum-os.org/git/doc
https://spectrum-os.org/git/mktuntap
https://spectrum-os.org/git/nixpkgs
https://spectrum-os.org/git/spectrum
https://spectrum-os.org/git/ucspi-vsock
https://spectrum-os.org/git/www
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).