From: colbyt <colby@colbyt.com>
To: devel@spectrum-os.org
Cc: colbyt <colby@colbyt.com>
Subject: [PATCH 6/8] pkgs/cloud-hypervisor: update GPU patchset to v52
Date: Fri, 26 Jun 2026 11:55:06 -0700 [thread overview]
Message-ID: <20260626185509.3715326-7-colby@colbyt.com> (raw)
In-Reply-To: <20260626185509.3715326-1-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.
Keep the local GPU support on top of that checkout, including the crosvm
SHMEM_MAP protocol-bit spelling needed by the crosvm GPU backend
packaged in the current nixpkgs pin.
The GPU frontend now uses the shared-memory region advertised by the
backend instead of assuming region 0, matching crosvm's host-visible
region ID.
The cargo vendor derivation 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 | 684 ++++++++----------
pkgs/cloud-hypervisor/default.nix | 77 +-
...ost_user-add-crosvm-shmem-map-compat.patch | 79 ++
4 files changed, 482 insertions(+), 396 deletions(-)
create mode 100644 pkgs/cloud-hypervisor/vhost/0003-vhost_user-add-crosvm-shmem-map-compat.patch
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..b5cd93b 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,423 @@
+// 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,23 @@ index 000000000..7eec07ba6
+
+ let avail_protocol_features = VhostUserProtocolFeatures::CONFIG
+ | VhostUserProtocolFeatures::BACKEND_REQ
-+ | VhostUserProtocolFeatures::SHARED_MEMORY_REGIONS;
++ | VhostUserProtocolFeatures::SHMEM_MAP;
+
+ 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()?;
++ let shmem_regions_count = shm_config
++ .memory_sizes
++ .iter()
++ .filter(|&&len| len != 0)
++ .count();
++ if shm_config.nregions != 1 || shmem_regions_count != 1 {
+ return Err(Error::VhostUserUnexpectedSharedMemoryRegionsCount(
+ 1,
-+ shm_regions.len(),
++ shmem_regions_count,
+ ));
+ }
-+ let shm_region = shm_regions[0];
+
+ Ok((
+ Gpu {
@@ -506,7 +514,7 @@ index 000000000..7eec07ba6
+ exit_evt,
+ iommu,
+ },
-+ shm_region,
++ shm_config,
+ ))
+ }
+
@@ -536,7 +544,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 +572,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 +616,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 +633,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 +643,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 +662,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 +723,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 +750,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 +788,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 +813,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 +858,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 +935,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 +967,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 +975,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 +989,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 +1036,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 +1085,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 +1108,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 +1169,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 +1180,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 +1225,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 +1239,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 +1249,7 @@ index 6d465047b..7eb1358e1 100644
// Add virtio-pmem if required
self.make_virtio_pmem_devices()?;
-@@ -3117,6 +3134,119 @@ impl DeviceManager {
+@@ -3234,6 +3252,129 @@ impl DeviceManager {
Ok(())
}
@@ -1308,12 +1257,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 +1271,46 @@ 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, shm_len) = shmem_config
++ .memory_sizes
++ .iter()
++ .copied()
++ .enumerate()
++ .find(|(_, len)| *len != 0)
++ .ok_or(DeviceManagerError::CreateVirtioGpu(
++ virtio_devices::vhost_user::Error::VhostUserInvalidSharedMemoryRegion,
++ ))?;
++ let shm_id = shm_id as u8;
++
+ // 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 +1335,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 +1355,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 +1379,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 +1387,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 +1446,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 +1511,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 +1555,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..f43b080 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,15 @@ 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
+ vhost/0003-vhost_user-add-crosvm-shmem-map-compat.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
diff --git a/pkgs/cloud-hypervisor/vhost/0003-vhost_user-add-crosvm-shmem-map-compat.patch b/pkgs/cloud-hypervisor/vhost/0003-vhost_user-add-crosvm-shmem-map-compat.patch
new file mode 100644
index 0000000..2a846bf
--- /dev/null
+++ b/pkgs/cloud-hypervisor/vhost/0003-vhost_user-add-crosvm-shmem-map-compat.patch
@@ -0,0 +1,79 @@
+From 4f0849043c9ef8d683f257f34e590a6842d7355c Mon Sep 17 00:00:00 2001
+From: Colby Townsend <colby@colbyt.com>
+Date: Fri, 26 Jun 2026 04:01:00 -0700
+Subject: [PATCH] vhost_user: add crosvm SHMEM_MAP compatibility
+SPDX-License-Identifier: Apache-2.0
+
+crosvm's vhost-user GPU backend advertises the shared-memory mapping
+protocol bit as SHMEM_MAP at 0x0010_0000. rust-vmm/vhost 0.16 uses
+SHMEM at 0x0020_0000 for the same GET_SHMEM_CONFIG and SHMEM_MAP/
+SHMEM_UNMAP flow.
+
+Accept either bit when checking local state, and expose the crosvm bit
+name so frontends can negotiate with crosvm without sending an
+unsupported protocol feature.
+
+Signed-off-by: Colby Townsend <colby@colbyt.com>
+---
+ vhost-user-backend/src/handler.rs | 4 +++-
+ vhost/src/vhost_user/backend_req_handler.rs | 4 +++-
+ vhost/src/vhost_user/frontend.rs | 4 +++-
+ vhost/src/vhost_user/message.rs | 2 ++
+ 4 files changed, 11 insertions(+), 3 deletions(-)
+
+diff --git a/vhost-user-backend/src/handler.rs b/vhost-user-backend/src/handler.rs
+index ea1fd6942..465dc2757 100644
+--- a/vhost-user-backend/src/handler.rs
++++ b/vhost-user-backend/src/handler.rs
+@@ -571,7 +571,9 @@ where
+ if self.acked_protocol_features & VhostUserProtocolFeatures::SHARED_OBJECT.bits() != 0 {
+ backend.set_shared_object_flag(true);
+ }
+- if self.acked_protocol_features & VhostUserProtocolFeatures::SHMEM.bits() != 0 {
++ let shmem_features = VhostUserProtocolFeatures::SHMEM
++ | VhostUserProtocolFeatures::SHMEM_MAP;
++ if self.acked_protocol_features & shmem_features.bits() != 0 {
+ backend.set_shmem_flag(true);
+ }
+ self.backend.set_backend_req_fd(backend);
+diff --git a/vhost/src/vhost_user/backend_req_handler.rs b/vhost/src/vhost_user/backend_req_handler.rs
+index d74b04558..fbe750c15 100644
+--- a/vhost/src/vhost_user/backend_req_handler.rs
++++ b/vhost/src/vhost_user/backend_req_handler.rs
+@@ -686,7 +686,9 @@ impl<S: VhostUserBackendReqHandler> BackendReqHandler<S> {
+ self.send_reply_message(&hdr, &msg)?;
+ }
+ Ok(FrontendReq::GET_SHMEM_CONFIG) => {
+- self.check_proto_feature(VhostUserProtocolFeatures::SHMEM)?;
++ self.check_proto_feature(
++ VhostUserProtocolFeatures::SHMEM | VhostUserProtocolFeatures::SHMEM_MAP,
++ )?;
+ let msg = self.backend.get_shmem_config()?;
+ self.send_reply_message(&hdr, &msg)?;
+ }
+diff --git a/vhost/src/vhost_user/frontend.rs b/vhost/src/vhost_user/frontend.rs
+index 195a6af1e..037f1b7f3 100644
+--- a/vhost/src/vhost_user/frontend.rs
++++ b/vhost/src/vhost_user/frontend.rs
+@@ -590,3 +590,5 @@ impl VhostUserFrontend for Frontend {
+ let mut node = self.node();
+- node.check_proto_feature(VhostUserProtocolFeatures::SHMEM)?;
++ node.check_proto_feature(
++ VhostUserProtocolFeatures::SHMEM | VhostUserProtocolFeatures::SHMEM_MAP,
++ )?;
+
+diff --git a/vhost/src/vhost_user/message.rs b/vhost/src/vhost_user/message.rs
+index 5826d19a6..006f2e0fe 100644
+--- a/vhost/src/vhost_user/message.rs
++++ b/vhost/src/vhost_user/message.rs
+@@ -441,6 +441,8 @@ bitflags! {
+ const DEVICE_STATE = 0x0008_0000;
+ /// Support suspend in-flight I/O requests and record them
+ const GET_VRING_BASE_INFLIGHT = 0x0010_0000;
++ /// crosvm name for the shared-memory mapping protocol bit.
++ const SHMEM_MAP = 0x0010_0000;
+ /// Allow the backend to request file descriptors be mapped into virtio shared memory
+ /// regions.
+ const SHMEM = 0x0020_0000;
+--
+2.50.0
--
2.54.0
next prev parent reply other threads:[~2026-06-26 18:55 UTC|newest]
Thread overview: 19+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-06-26 18:55 [PATCH 0/8] refresh nixpkgs for Linux 7.1 colbyt
2026-06-26 18:55 ` [PATCH 1/8] pkgs: fix aarch64-musl builds with current nixpkgs colbyt
2026-07-02 12:18 ` Alyssa Ross
2026-06-26 18:55 ` [PATCH 2/8] lib: update nixpkgs colbyt
2026-06-26 18:55 ` [PATCH 3/8] pkgs/skaware: vendor backported patches colbyt
2026-07-02 11:53 ` Alyssa Ross
2026-06-26 18:55 ` [PATCH 4/8] pkgs/gtk3: skip integrated Wayland backport colbyt
2026-07-02 12:19 ` Alyssa Ross
2026-06-26 18:55 ` [PATCH 5/8] pkgs/skaware: skip integrated backports colbyt
2026-06-26 18:55 ` colbyt [this message]
2026-06-26 18:55 ` [PATCH 7/8] pkgs/libfyaml: fix pkg-config libs colbyt
2026-06-26 18:55 ` [PATCH 8/8] vm-lib: allow app VMs to name closure roots colbyt
2026-07-02 13:38 ` Alyssa Ross
2026-07-02 23:40 ` colby
2026-07-03 14:02 ` Alyssa Ross
2026-06-26 18:55 ` [PATCH optional] linux: use 6.18 for generic images colbyt
2026-07-02 13:42 ` Alyssa Ross
2026-07-02 23:20 ` colby
2026-07-02 12:03 ` [PATCH 0/8] refresh nixpkgs for Linux 7.1 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=20260626185509.3715326-7-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).