From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from atuin.qyliss.net (localhost [IPv6:::1]) by atuin.qyliss.net (Postfix) with ESMTP id 8DCB6A2EC; Thu, 25 Jun 2026 17:49:41 +0000 (UTC) Received: by atuin.qyliss.net (Postfix, from userid 993) id ACF83A339; Thu, 25 Jun 2026 17:49:38 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 4.0.1 (2024-03-26) on atuin.qyliss.net X-Spam-Level: X-Spam-Status: No, score=-0.8 required=3.0 tests=DKIM_SIGNED,DKIM_VALID, DKIM_VALID_AU,DMARC_PASS,RCVD_IN_DNSWL_LOW,SPF_HELO_PASS, T_FILL_THIS_FORM_SHORT autolearn=unavailable autolearn_force=no version=4.0.1 Received: from mail-43172.protonmail.ch (mail-43172.protonmail.ch [185.70.43.172]) by atuin.qyliss.net (Postfix) with ESMTPS id AE4B8A281 for ; Thu, 25 Jun 2026 17:49:33 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=colbyt.com; s=protonmail; t=1782409769; x=1782668969; bh=KTDEQ1FWJrMc+cvpfrHea6hhjTxwY+4VCuYg/mcui4o=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References:From:To: Cc:Date:Subject:Reply-To:Feedback-ID:Message-ID:BIMI-Selector; b=e6fXCGWANdzblka6Fp61zRkUWyeBWBVG2ou+TbLej5pdV4HutZgHGu6F3SFHonFh9 ZyGi5gvLWPFRpjt66iJs2HjOXtsLddG++FfBpT8IabaL7RLfXDdS8UAe2SEn8e28Qk KTAvsWDJgshqwNMuTnvYPpygz9LQWneYtXjTD8hKuYG+FMfB9WkD/AIV6DuHZDRTC1 m+aYxiMvUxwULJQ7KmKPDK0j/LepZoneVMq6TvJ8w/I8IvxWHMeIfTgkyY7JfLcapq iPj5RPuTshG6Yw5nWd+2zSZL1MngsP9RELmTxvK4W3SuBsgz/0jVqKg3fthhmyfD3Z cRedRTbSZ3nLw== X-Pm-Submission-Id: 4gmRBs5z24z1DFGL From: colbyt To: devel@spectrum-os.org Subject: [PATCH 2/6] pkgs/cloud-hypervisor: update GPU patchset to v52 Date: Thu, 25 Jun 2026 10:48:45 -0700 Message-ID: <7cb1c12557f07e353186254250bfea29e36c8f30.1782409229.git.colby@colbyt.com> X-Mailer: git-send-email 2.54.0 In-Reply-To: References: MIME-Version: 1.0 Content-Transfer-Encoding: 8bit Message-ID-Hash: 7KMNELFTHLPO3TZ72AIIUIBTRBTNTNTR X-Message-ID-Hash: 7KMNELFTHLPO3TZ72AIIUIBTRBTNTNTR X-MailFrom: colby@colbyt.com X-Mailman-Rule-Misses: dmarc-mitigation; no-senders; approved; loop; banned-address; header-match-devel.spectrum-os.org-0; header-match-devel.spectrum-os.org-1; header-match-devel.spectrum-os.org-2; header-match-devel.spectrum-os.org-3; header-match-devel.spectrum-os.org-4; emergency; member-moderation; nonmember-moderation; administrivia; implicit-dest; max-recipients; max-size; news-moderation; no-subject; digests; suspicious-header CC: colbyt X-Mailman-Version: 3.3.10 Precedence: list List-Id: Patches and low-level development discussion Archived-At: List-Archive: List-Help: List-Owner: List-Post: List-Subscribe: List-Unsubscribe: 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 --- .../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 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 SPDX-License-Identifier: Apache-2.0 AND LicenseRef-BSD-3-Clause-Google Signed-off-by: Alyssa Ross Signed-off-by: Alyssa Ross +Signed-off-by: colbyt --- 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 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 Co-authored-by: Alyssa Ross Signed-off-by: Alyssa Ross +Signed-off-by: colbyt --- - 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>; - fn vm_add_disk(&self, disk_config: &str) -> zbus::Result>; - fn vm_add_fs(&self, fs_config: &str) -> zbus::Result>; +@@ -93,6 +95,7 @@ trait DBusApi1 { + &self, + generic_vhost_user_config: &str, + ) -> zbus::Result>; + fn vm_add_gpu(&self, gpu_config: &str) -> zbus::Result>; fn vm_add_net(&self, net_config: &str) -> zbus::Result>; fn vm_add_pmem(&self, pmem_config: &str) -> zbus::Result>; fn vm_add_user_device(&self, vm_add_user_device: &str) -> zbus::Result>; -@@ -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 { - Ok(fs_config) +@@ -875,6 +903,13 @@ fn add_generic_vhost_user_config(config: &str) -> Result { + Ok(generic_vhost_user_config) } +fn add_gpu_config(config: &str) -> Result { @@ -143,12 +142,12 @@ index fd48ffab1..680a2b62f 100644 fn add_pmem_config(config: &str) -> Result { 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=") - .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, @@ -215,31 +211,33 @@ index f0ed28f51..892bf08ee 100644 + pub region_list: BTreeMap, } - /// 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)> { +@@ -219,6 +220,18 @@ fn virtio_generic_vhost_user_thread_rules() -> Vec<(i64, Vec)> { ] } @@ -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)> { vec![] } -@@ -271,6 +286,7 @@ fn get_seccomp_rules(thread_type: Thread) -> Vec<(i64, Vec)> { +@@ -299,6 +312,7 @@ fn get_seccomp_rules(thread_type: Thread) -> Vec<(i64, Vec)> { 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 @@ -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 { ++ fn shmem_map(&self, req: &VhostUserMMap, fd: &dyn AsRawFd) -> HandlerResult { + 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 { ++ fn shmem_unmap(&self, req: &VhostUserMMap) -> HandlerResult { + 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, -+ interrupt_cb: Arc, -+ 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> { ++ 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> { ++ pub fn get_shmem_config(&mut self) -> Result { + 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> { @@ -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 = 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 = 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>, VmError>; +@@ -561,6 +565,8 @@ pub trait RequestHandler { + fs_cfg: GenericVhostUserConfig, + ) -> Result>, VmError>; + fn vm_add_gpu(&mut self, gpu_cfg: GpuConfig) -> Result>, VmError>; + fn vm_add_pmem(&mut self, pmem_cfg: PmemConfig) -> Result>, VmError>; fn vm_add_net(&mut self, net_cfg: NetConfig) -> Result>, 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>, + pub generic_vhost_user: Option>, + pub gpu: Option>, pub pmem: Option>, pub serial: &'a str, pub console: &'a str, -@@ -451,6 +458,9 @@ impl<'a> VmParams<'a> { - let fs: Option> = args - .get_many::("fs") +@@ -524,6 +531,9 @@ impl<'a> VmParams<'a> { + let generic_vhost_user: Option> = args + .get_many::("generic-vhost-user") .map(|x| x.map(|y| y as &str).collect()); + let gpu: Option> = args + .get_many::("gpu") @@ -1044,65 +1034,45 @@ index 78d6f9f1e..e1a54b0fa 100644 let pmem: Option> = args .get_many::("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=,id=,pci_segment=\""; ++ \"socket=,id=,pci_segment=,pci_device_id=\""; + + pub fn parse(gpu: &str) -> Result { + 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=,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> = None; @@ -1136,77 +1106,53 @@ index 78d6f9f1e..e1a54b0fa 100644 let mut pmem: Option> = 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 { -+ 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>, -+ 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 { -+ 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 { - 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>, 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, -+ #[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, + pub generic_vhost_user: Option>, pub fs: Option>, + pub gpu: Option>, pub pmem: Option>, - #[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