* [PATCH 0/8] refresh nixpkgs for Linux 7.1
@ 2026-06-26 18:55 colbyt
2026-06-26 18:55 ` [PATCH 1/8] pkgs: fix aarch64-musl builds with current nixpkgs colbyt
` (9 more replies)
0 siblings, 10 replies; 19+ messages in thread
From: colbyt @ 2026-06-26 18:55 UTC (permalink / raw)
To: devel; +Cc: colbyt
This series moves the default nixpkgs pin forward and fixes the build
and runtime issues exposed on the generic Spectrum path. It lets the
generic images follow linux_latest, which currently selects Linux 7.1.1.
The changes are split by cause: aarch64-musl build fixes exposed by the
pin bump, integrated skaware and GTK backports, Cloud Hypervisor 52.0
with the local vhost-user GPU patchset rebased, the libfyaml pkg-config
cleanup needed by AppStream, and the app VM closure-root fix for foot
and Firefox.
The Cloud Hypervisor update includes the crosvm SHMEM_MAP compatibility
needed by the current crosvm GPU backend.
I am also sending one optional follow-up patch that keeps the generic
images on linux_6_18 instead. It is the same code path plus a small
kernel package selection patch, and updates the conservative LTS track
from Linux 6.18.2 to the 6.18.36 package from the new nixpkgs pin. That
variant passed the full integration suite on Linux 6.18.36.
Tested on aarch64 with nix-portable:
- cloud-hypervisor package build and cargo checks
- full integration suite: late-serial, appimage, networking, portal on
Linux 7.1.1
colbyt (8):
pkgs: fix aarch64-musl builds with current nixpkgs
lib: update nixpkgs
pkgs/skaware: vendor backported patches
pkgs/gtk3: skip integrated Wayland backport
pkgs/skaware: skip integrated backports
pkgs/cloud-hypervisor: update GPU patchset to v52
pkgs/libfyaml: fix pkg-config libs
vm-lib: allow app VMs to name closure roots
lib/nixpkgs.default.nix | 4 +-
.../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 ++
pkgs/gtk3/default.nix | 4 +-
pkgs/overlay.nix | 112 +++
...d-don-t-chmod-device-nodes-for-lines.patch | 10 +
...limit-add-p-option-for-rlimit-rtprio.patch | 25 +
pkgs/skaware-packages/default.nix | 20 +-
vm-lib/make-vm.nix | 4 +-
vm/app/firefox.nix | 1 +
vm/app/foot.nix | 1 +
13 files changed, 645 insertions(+), 414 deletions(-)
create mode 100644 pkgs/cloud-hypervisor/vhost/0003-vhost_user-add-crosvm-shmem-map-compat.patch
create mode 100644 pkgs/skaware-packages/0001-mdevd-don-t-chmod-device-nodes-for-lines.patch
create mode 100644 pkgs/skaware-packages/0001-s6-softlimit-add-p-option-for-rlimit-rtprio.patch
--
2.54.0
^ permalink raw reply [flat|nested] 19+ messages in thread
* [PATCH 1/8] pkgs: fix aarch64-musl builds with current nixpkgs
2026-06-26 18:55 [PATCH 0/8] refresh nixpkgs for Linux 7.1 colbyt
@ 2026-06-26 18:55 ` colbyt
2026-07-02 12:18 ` Alyssa Ross
2026-06-26 18:55 ` [PATCH 2/8] lib: update nixpkgs colbyt
` (8 subsequent siblings)
9 siblings, 1 reply; 19+ messages in thread
From: colbyt @ 2026-06-26 18:55 UTC (permalink / raw)
To: devel; +Cc: colbyt
The newer nixpkgs pin exposes several aarch64-musl build issues in
Spectrum dependencies.
Normalize Python bootstrap outputs that install under usr/, patch the
generated pyproject-build wrapper to include those paths, and keep the
GnuTLS STARTTLS tests from observing a host /usr/bin/socat that is not
on PATH.
Also skip the exact psutil and mypy tests that depend on host network or
unsandboxed root directory details. The remaining package test suites
pass with those exact deselections.
Signed-off-by: colbyt <colby@colbyt.com>
---
pkgs/overlay.nix | 105 +++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 105 insertions(+)
diff --git a/pkgs/overlay.nix b/pkgs/overlay.nix
index 3e3336e..66fea11 100644
--- a/pkgs/overlay.nix
+++ b/pkgs/overlay.nix
@@ -4,12 +4,117 @@
(final: super: {
cloud-hypervisor = import ./cloud-hypervisor { inherit final super; };
+ coreutils = super.coreutils.overrideAttrs ({ postPatch ? "", ... }: (
+ final.lib.optionalAttrs
+ (super.stdenv.hostPlatform.isAarch64 && super.stdenv.hostPlatform.isMusl)
+ {
+ postPatch = postPatch + ''
+ # These locale-sensitive tests fail in the aarch64-musl bootstrap build.
+ for f in \
+ tests/cut/mb-non-utf8.sh \
+ tests/date/date-locale-hour.sh \
+ tests/dd/conv-case.sh \
+ tests/numfmt/mb-non-utf8.sh \
+ tests/paste/multi-byte.sh \
+ tests/sort/sort-h-thousands-sep.sh \
+ tests/sort/sort-month.sh
+ do
+ sed '2i echo Skipping aarch64-musl locale test && exit 77' -i "$f"
+ done
+ '';
+ }
+ ));
+
+ python313 = super.python313.override {
+ packageOverrides = _pythonFinal: pythonSuper:
+ let
+ # Some aarch64-musl bootstrap wheels install below usr/.
+ normalizeBootstrapOutput = drv:
+ drv.overrideAttrs ({ postInstall ? "", ... }: (
+ final.lib.optionalAttrs
+ (super.stdenv.hostPlatform.isAarch64 && super.stdenv.hostPlatform.isMusl)
+ {
+ postInstall = postInstall + ''
+ if [ -d "$out/usr" ]; then
+ cp -a "$out"/usr/. "$out"/
+ rm -rf "$out/usr"
+ fi
+ '';
+ }
+ ));
+ in
+ {
+ bootstrap = pythonSuper.bootstrap // {
+ build = pythonSuper.bootstrap.build.overrideAttrs ({ installPhase ? "", ... }: (
+ final.lib.optionalAttrs
+ (super.stdenv.hostPlatform.isAarch64 && super.stdenv.hostPlatform.isMusl)
+ {
+ installPhase = builtins.replaceStrings
+ [ "\nwrapProgram $out/bin/pyproject-build" ]
+ [ ''
+
+ if [ -d "$out/usr" ]; then
+ cp -a "$out"/usr/. "$out"/
+ rm -rf "$out/usr"
+ fi
+ chmod +x "$out/bin/pyproject-build"
+ wrapProgram $out/bin/pyproject-build'' ]
+ installPhase + ''
+
+ sed -E -i \
+ 's#(/nix/store/[^:"]+-python3[.]13-bootstrap-(packaging|pyproject-hooks|tomli)-[^/:"]*)/lib/python3[.]13/site-packages#\1/lib/python3.13/site-packages:\1/usr/lib/python3.13/site-packages#g' \
+ "$out/bin/pyproject-build"
+ '';
+ }
+ ));
+
+ installer = normalizeBootstrapOutput pythonSuper.bootstrap.installer;
+ packaging = normalizeBootstrapOutput pythonSuper.bootstrap.packaging;
+ };
+
+ psutil = pythonSuper.psutil.overrideAttrs ({ disabledTestPaths ? [], ... }: (
+ final.lib.optionalAttrs
+ (super.stdenv.hostPlatform.isAarch64 && super.stdenv.hostPlatform.isMusl)
+ {
+ disabledTestPaths = disabledTestPaths ++ [
+ # The test depends on host interface broadcast semantics.
+ "tests/test_system.py::TestNetAPIs::test_net_if_addrs"
+ ];
+ }
+ ));
+
+ mypy = pythonSuper.mypy.overrideAttrs ({ disabledTestPaths ? [], ... }: (
+ final.lib.optionalAttrs
+ (super.stdenv.hostPlatform.isAarch64 && super.stdenv.hostPlatform.isMusl)
+ {
+ disabledTestPaths = disabledTestPaths ++ [
+ # The fake root source test observes the unsandboxed build root.
+ "mypy/test/test_find_sources.py::SourceFinderSuite::test_find_sources_exclude"
+ ];
+ }
+ ));
+ };
+ };
+
flatpak = super.flatpak.override (
final.lib.optionalAttrs final.stdenv.hostPlatform.isMusl {
withMalcontent = false;
}
);
+ gnutls = super.gnutls.overrideAttrs ({ postPatch ? "", ... }: (
+ final.lib.optionalAttrs
+ (super.stdenv.hostPlatform.isAarch64 && super.stdenv.hostPlatform.isMusl)
+ {
+ postPatch = postPatch + ''
+ # The test later executes socat from PATH, not /usr/bin.
+ substituteInPlace tests/scripts/starttls-common.sh \
+ --replace-fail 'if test ! -x /usr/bin/socat;then' \
+ 'if ! command -v socat >/dev/null 2>&1; then'
+ '';
+ }
+ ));
+
gtk3 = import ./gtk3 { inherit final super; };
mailutils = super.mailutils.overrideAttrs (_: (
--
2.54.0
^ permalink raw reply related [flat|nested] 19+ messages in thread
* [PATCH 2/8] lib: update nixpkgs
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-06-26 18:55 ` colbyt
2026-06-26 18:55 ` [PATCH 3/8] pkgs/skaware: vendor backported patches colbyt
` (7 subsequent siblings)
9 siblings, 0 replies; 19+ messages in thread
From: colbyt @ 2026-06-26 18:55 UTC (permalink / raw)
To: devel; +Cc: colbyt
Move the default nixpkgs pin to
667d5cf1c59585031d743c78b394b0a647537c35.
On the generic Spectrum paths this currently selects Linux 7.1.1 through
linux_latest.
Tested with the tools test suite and the host, app VM, and net VM kernel
config builds. The net VM config built as
/nix/store/k0314d1ck5wnj6mnh1w4ncsbqjcplk9y-linux-config-7.1.1.
Signed-off-by: colbyt <colby@colbyt.com>
---
lib/nixpkgs.default.nix | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/lib/nixpkgs.default.nix b/lib/nixpkgs.default.nix
index 6b1b26f..bc66b36 100644
--- a/lib/nixpkgs.default.nix
+++ b/lib/nixpkgs.default.nix
@@ -4,6 +4,6 @@
# Generated by scripts/update-nixpkgs.sh.
import (builtins.fetchTarball {
- url = "https://github.com/NixOS/nixpkgs/archive/cab52b36dca5a5a368f05bd03fca0b543b5b9a3e.tar.gz";
- sha256 = "161vhvxj5lmarlagrgcak8yvgwd1llcbfm7g1vqhppy1a7v73y2a";
+ url = "https://github.com/NixOS/nixpkgs/archive/667d5cf1c59585031d743c78b394b0a647537c35.tar.gz";
+ sha256 = "sha256-QyuGP5+QOtmXpy4i2X4DhBVBaySBdDKQEhqKcphcp34=";
})
--
2.54.0
^ permalink raw reply related [flat|nested] 19+ messages in thread
* [PATCH 3/8] pkgs/skaware: vendor backported patches
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-06-26 18:55 ` [PATCH 2/8] lib: update nixpkgs colbyt
@ 2026-06-26 18:55 ` colbyt
2026-07-02 11:53 ` Alyssa Ross
2026-06-26 18:55 ` [PATCH 4/8] pkgs/gtk3: skip integrated Wayland backport colbyt
` (6 subsequent siblings)
9 siblings, 1 reply; 19+ messages in thread
From: colbyt @ 2026-06-26 18:55 UTC (permalink / raw)
To: devel; +Cc: colbyt
Two skaware backports were fetched from cgit patch endpoints. Those
endpoints are not stable enough for package inputs: the same URL can
return an unrelated patch, breaking the build before the VM can start.
Keep the small upstream diffs in-tree instead. The package still
applies the same s6 and mdevd fixes, and the comments next to each patch
record the upstream commit IDs.
Signed-off-by: colbyt <colby@colbyt.com>
---
...d-don-t-chmod-device-nodes-for-lines.patch | 10 ++++++++
...limit-add-p-option-for-rlimit-rtprio.patch | 25 +++++++++++++++++++
pkgs/skaware-packages/default.nix | 12 +++------
3 files changed, 39 insertions(+), 8 deletions(-)
create mode 100644 pkgs/skaware-packages/0001-mdevd-don-t-chmod-device-nodes-for-lines.patch
create mode 100644 pkgs/skaware-packages/0001-s6-softlimit-add-p-option-for-rlimit-rtprio.patch
diff --git a/pkgs/skaware-packages/0001-mdevd-don-t-chmod-device-nodes-for-lines.patch b/pkgs/skaware-packages/0001-mdevd-don-t-chmod-device-nodes-for-lines.patch
new file mode 100644
index 0000000..919f412
--- /dev/null
+++ b/pkgs/skaware-packages/0001-mdevd-don-t-chmod-device-nodes-for-lines.patch
@@ -0,0 +1,10 @@
+SPDX-FileCopyrightText: 2025 Alyssa Ross <hi@alyssa.is>
+SPDX-License-Identifier: ISC
+
+diff --git a/src/mdevd/mdevd.c b/src/mdevd/mdevd.c
+index 3040ba6..aecd5a7 100644
+--- a/src/mdevd/mdevd.c
++++ b/src/mdevd/mdevd.c
+@@ -643 +643 @@ static inline int run_scriptelem (struct uevent_s const *event, scriptelem const
+- if (nodelen && ud->action == ACTION_ADD && ud->mmaj >= 0)
++ if (elem->movetype != MOVEINFO_NOCREATE && nodelen && ud->action == ACTION_ADD && ud->mmaj >= 0)
diff --git a/pkgs/skaware-packages/0001-s6-softlimit-add-p-option-for-rlimit-rtprio.patch b/pkgs/skaware-packages/0001-s6-softlimit-add-p-option-for-rlimit-rtprio.patch
new file mode 100644
index 0000000..b1aa586
--- /dev/null
+++ b/pkgs/skaware-packages/0001-s6-softlimit-add-p-option-for-rlimit-rtprio.patch
@@ -0,0 +1,25 @@
+SPDX-FileCopyrightText: 2025 Alyssa Ross <hi@alyssa.is>
+SPDX-License-Identifier: ISC
+
+diff --git a/doc/s6-softlimit.html b/doc/s6-softlimit.html
+index 05701ce..49a5b40 100644
+--- a/doc/s6-softlimit.html
++++ b/doc/s6-softlimit.html
+@@ -28 +28 @@ s6-softlimit changes its process limits, then executes into another program.
+- s6-softlimit [ -H | -h ] [ -a <em>allmem</em> ] [ -c <em>core</em> ] [ -d <em>data</em> ] [ -f <em>fsize</em> ] [ -l <em>lock</em> ] [ -m <em>mem</em> ] [ -o <em>ofiles</em> ] [ -p <em>proc</em> ] [ -r <em>res</em> ] [ -s <em>stack</em> ] [ -t <em>cpusecs</em> ] <em>prog...</em>
++ s6-softlimit [ -H | -h ] [ -a <em>allmem</em> ] [ -c <em>core</em> ] [ -d <em>data</em> ] [ -f <em>fsize</em> ] [ -l <em>lock</em> ] [ -m <em>mem</em> ] [ -o <em>ofiles</em> ] [ -P <em>prio</em> ] [ -p <em>proc</em> ] [ -r <em>res</em> ] [ -s <em>stack</em> ] [ -t <em>cpusecs</em> ] <em>prog...</em>
+@@ -60,0 +61 @@ and s6-softlimit will die. There is virtually no reason to ever use this. </li>
++ <li> <tt>-P <em>prio</em></tt> : limit the real-time priority to <em>prio</em>. </li>
+diff --git a/src/daemontools-extras/s6-softlimit.c b/src/daemontools-extras/s6-softlimit.c
+index d6112b2..beb7325 100644
+--- a/src/daemontools-extras/s6-softlimit.c
++++ b/src/daemontools-extras/s6-softlimit.c
+@@ -44 +44 @@ int main (int argc, char const *const *argv)
+- int opt = subgetopt_r(argc, argv, "hHa:c:d:f:l:m:o:p:r:s:t:", &l) ;
++ int opt = subgetopt_r(argc, argv, "hHa:c:d:f:l:m:o:P:p:r:s:t:", &l) ;
+@@ -105,0 +106,5 @@ int main (int argc, char const *const *argv)
++#endif
++ break ;
++ case 'P' :
++#ifdef RLIMIT_RTPRIO
++ doit(RLIMIT_RTPRIO, l.arg) ;
diff --git a/pkgs/skaware-packages/default.nix b/pkgs/skaware-packages/default.nix
index e248201..1489317 100644
--- a/pkgs/skaware-packages/default.nix
+++ b/pkgs/skaware-packages/default.nix
@@ -6,19 +6,15 @@ import ../../lib/overlay-package.nix [ "skawarePackages" ] ({ final, super }:
super.skawarePackages.overrideScope (_: prev: {
s6 = prev.s6.overrideAttrs ({ patches ? [], ... }: {
patches = patches ++ [
- (final.fetchpatch {
- url = "https://git.skarnet.org/cgi-bin/cgit.cgi/s6/patch/?id=c3a8ef7034fb2bc02f35381a8970ac026822a810";
- hash = "sha256-lgCoPbEYru6/a2bpVpLsZ2Rq2OHhNVs0lDgFO/df1Aw=";
- })
+ # Upstream c3a8ef70; vendored because cgit patch URLs are unstable.
+ ./0001-s6-softlimit-add-p-option-for-rlimit-rtprio.patch
];
});
mdevd = prev.mdevd.overrideAttrs ({ patches ? [], ... }: {
patches = patches ++ [
- (final.fetchpatch {
- url = "https://git.skarnet.org/cgi-bin/cgit.cgi/mdevd/patch/?id=252f241e425bf09ddfb4a824e40403f40da0da1e";
- hash = "sha256-0tEC+yJGyPapsxBqzBXPztF3bl7OwjVAGjhNXtwZQ0g=";
- })
+ # Upstream 252f241e; vendored because cgit patch URLs are unstable.
+ ./0001-mdevd-don-t-chmod-device-nodes-for-lines.patch
];
});
}))
--
2.54.0
^ permalink raw reply related [flat|nested] 19+ messages in thread
* [PATCH 4/8] pkgs/gtk3: skip integrated Wayland backport
2026-06-26 18:55 [PATCH 0/8] refresh nixpkgs for Linux 7.1 colbyt
` (2 preceding siblings ...)
2026-06-26 18:55 ` [PATCH 3/8] pkgs/skaware: vendor backported patches colbyt
@ 2026-06-26 18:55 ` colbyt
2026-07-02 12:19 ` Alyssa Ross
2026-06-26 18:55 ` [PATCH 5/8] pkgs/skaware: skip integrated backports colbyt
` (5 subsequent siblings)
9 siblings, 1 reply; 19+ messages in thread
From: colbyt @ 2026-06-26 18:55 UTC (permalink / raw)
To: devel; +Cc: colbyt
The updated nixpkgs pin already contains the GTK Wayland backport carried
by Spectrum.
Drop the local patch from the package override so the build does not try
to apply an already-integrated change.
Signed-off-by: colbyt <colby@colbyt.com>
---
pkgs/gtk3/default.nix | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/pkgs/gtk3/default.nix b/pkgs/gtk3/default.nix
index 72445c9..47c5a14 100644
--- a/pkgs/gtk3/default.nix
+++ b/pkgs/gtk3/default.nix
@@ -3,8 +3,8 @@
import ../../lib/overlay-package.nix [ "gtk3" ] ({ final, super }:
-super.gtk3.overrideAttrs ({ patches ? [], ... }: {
- patches = patches ++ [
+super.gtk3.overrideAttrs ({ patches ? [], version, ... }: {
+ patches = patches ++ final.lib.optionals (final.lib.versionOlder version "3.24.52") [
(final.fetchpatch {
url = "https://gitlab.gnome.org/GNOME/gtk/-/commit/8569e206badbee1b27ff0e27316391b8d8c3f987.patch";
hash = "sha256-OdBhCGtz+3HS8LRhp+GCj3dL4pntybiI9b3A3kc5+OY=";
--
2.54.0
^ permalink raw reply related [flat|nested] 19+ messages in thread
* [PATCH 5/8] pkgs/skaware: skip integrated backports
2026-06-26 18:55 [PATCH 0/8] refresh nixpkgs for Linux 7.1 colbyt
` (3 preceding siblings ...)
2026-06-26 18:55 ` [PATCH 4/8] pkgs/gtk3: skip integrated Wayland backport colbyt
@ 2026-06-26 18:55 ` colbyt
2026-06-26 18:55 ` [PATCH 6/8] pkgs/cloud-hypervisor: update GPU patchset to v52 colbyt
` (4 subsequent siblings)
9 siblings, 0 replies; 19+ messages in thread
From: colbyt @ 2026-06-26 18:55 UTC (permalink / raw)
To: devel; +Cc: colbyt
The updated nixpkgs pin already contains the s6 softlimit and mdevd
backports carried by Spectrum.
Leave the vendored patch files in-tree for older pins, but stop applying
them when building against this nixpkgs revision.
Signed-off-by: colbyt <colby@colbyt.com>
---
pkgs/skaware-packages/default.nix | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/pkgs/skaware-packages/default.nix b/pkgs/skaware-packages/default.nix
index 1489317..2e9244b 100644
--- a/pkgs/skaware-packages/default.nix
+++ b/pkgs/skaware-packages/default.nix
@@ -4,15 +4,15 @@
import ../../lib/overlay-package.nix [ "skawarePackages" ] ({ final, super }:
super.skawarePackages.overrideScope (_: prev: {
- s6 = prev.s6.overrideAttrs ({ patches ? [], ... }: {
- patches = patches ++ [
+ s6 = prev.s6.overrideAttrs ({ patches ? [], version, ... }: {
+ patches = patches ++ final.lib.optionals (final.lib.versionOlder version "2.15.0.0") [
# Upstream c3a8ef70; vendored because cgit patch URLs are unstable.
./0001-s6-softlimit-add-p-option-for-rlimit-rtprio.patch
];
});
- mdevd = prev.mdevd.overrideAttrs ({ patches ? [], ... }: {
- patches = patches ++ [
+ mdevd = prev.mdevd.overrideAttrs ({ patches ? [], version, ... }: {
+ patches = patches ++ final.lib.optionals (final.lib.versionOlder version "0.1.8.2") [
# Upstream 252f241e; vendored because cgit patch URLs are unstable.
./0001-mdevd-don-t-chmod-device-nodes-for-lines.patch
];
--
2.54.0
^ permalink raw reply related [flat|nested] 19+ messages in thread
* [PATCH 6/8] pkgs/cloud-hypervisor: update GPU patchset to v52
2026-06-26 18:55 [PATCH 0/8] refresh nixpkgs for Linux 7.1 colbyt
` (4 preceding siblings ...)
2026-06-26 18:55 ` [PATCH 5/8] pkgs/skaware: skip integrated backports colbyt
@ 2026-06-26 18:55 ` colbyt
2026-06-26 18:55 ` [PATCH 7/8] pkgs/libfyaml: fix pkg-config libs colbyt
` (3 subsequent siblings)
9 siblings, 0 replies; 19+ messages in thread
From: colbyt @ 2026-06-26 18:55 UTC (permalink / raw)
To: devel; +Cc: colbyt
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
^ permalink raw reply related [flat|nested] 19+ messages in thread
* [PATCH 7/8] pkgs/libfyaml: fix pkg-config libs
2026-06-26 18:55 [PATCH 0/8] refresh nixpkgs for Linux 7.1 colbyt
` (5 preceding siblings ...)
2026-06-26 18:55 ` [PATCH 6/8] pkgs/cloud-hypervisor: update GPU patchset to v52 colbyt
@ 2026-06-26 18:55 ` colbyt
2026-06-26 18:55 ` [PATCH 8/8] vm-lib: allow app VMs to name closure roots colbyt
` (2 subsequent siblings)
9 siblings, 0 replies; 19+ messages in thread
From: colbyt @ 2026-06-26 18:55 UTC (permalink / raw)
To: devel; +Cc: colbyt
The current nixpkgs libfyaml package can install a malformed Libs line
containing the tokens "none required".
AppStream consumes libfyaml.pc when building the Spectrum integration
closure, and those stray tokens make the link step fail before the VM
tests run.
Normalize the generated pkg-config file in postInstall until the pinned
nixpkgs package no longer needs the workaround.
Signed-off-by: colbyt <colby@colbyt.com>
---
pkgs/overlay.nix | 7 +++++++
1 file changed, 7 insertions(+)
diff --git a/pkgs/overlay.nix b/pkgs/overlay.nix
index 66fea11..559e361 100644
--- a/pkgs/overlay.nix
+++ b/pkgs/overlay.nix
@@ -115,6 +115,13 @@
}
));
+ libfyaml = super.libfyaml.overrideAttrs ({ postInstall ? "", ... }: {
+ postInstall = postInstall + ''
+ sed -i 's/ -lpthread none required -lfyaml/ -lpthread -lfyaml/' \
+ "$dev/lib/pkgconfig/libfyaml.pc"
+ '';
+ });
+
gtk3 = import ./gtk3 { inherit final super; };
mailutils = super.mailutils.overrideAttrs (_: (
--
2.54.0
^ permalink raw reply related [flat|nested] 19+ messages in thread
* [PATCH 8/8] vm-lib: allow app VMs to name closure roots
2026-06-26 18:55 [PATCH 0/8] refresh nixpkgs for Linux 7.1 colbyt
` (6 preceding siblings ...)
2026-06-26 18:55 ` [PATCH 7/8] pkgs/libfyaml: fix pkg-config libs colbyt
@ 2026-06-26 18:55 ` colbyt
2026-07-02 13:38 ` Alyssa Ross
2026-06-26 18:55 ` [PATCH optional] linux: use 6.18 for generic images colbyt
2026-07-02 12:03 ` [PATCH 0/8] refresh nixpkgs for Linux 7.1 Alyssa Ross
9 siblings, 1 reply; 19+ messages in thread
From: colbyt @ 2026-06-26 18:55 UTC (permalink / raw)
To: devel; +Cc: colbyt
make-vm copies the closure of the run path into the image.
For app VMs that use lib.getExe, that can miss files from the package
output that owns the executable. Allow callers to pass explicit closure
roots, and use the package derivations for the foot and Firefox app VMs.
Signed-off-by: colbyt <colby@colbyt.com>
---
vm-lib/make-vm.nix | 4 ++--
vm/app/firefox.nix | 1 +
| 1 +
3 files changed, 4 insertions(+), 2 deletions(-)
diff --git a/vm-lib/make-vm.nix b/vm-lib/make-vm.nix
index 7847883..9f11bbd 100644
--- a/vm-lib/make-vm.nix
+++ b/vm-lib/make-vm.nix
@@ -14,7 +14,7 @@ pkgs.pkgsStatic.callPackage (
{ lib, runCommand, writeClosure, erofs-utils }:
-{ run, type, providers ? {}, sharedDirs ? {} }:
+{ run, runClosure ? [ run ], type, providers ? {}, sharedDirs ? {} }:
let
inherit (lib) any attrValues concatLists hasInfix mapAttrsToList;
@@ -38,7 +38,7 @@ runCommand "spectrum-vm" {
echo ${type} > fs/type
ln -s ${run} fs/run
mkdir -p fs${builtins.storeDir}
- comm -23 <(sort ${writeClosure [ run ]}) \
+ comm -23 <(sort ${writeClosure runClosure}) \
<(sort ${writeClosure [ basePaths ]}) |
xargs -rd '\n' cp -rvt fs${builtins.storeDir}
diff --git a/vm/app/firefox.nix b/vm/app/firefox.nix
index 164453c..6b84a30 100644
--- a/vm/app/firefox.nix
+++ b/vm/app/firefox.nix
@@ -8,4 +8,5 @@ callSpectrumPackage ../make-vm.nix {} {
providers.net = [ "sys.netvm" ];
type = "nix";
run = lib.getExe firefox;
+ runClosure = [ firefox ];
}) (_: {})
--git a/vm/app/foot.nix b/vm/app/foot.nix
index 332ccf4..62d7aba 100644
--- a/vm/app/foot.nix
+++ b/vm/app/foot.nix
@@ -7,4 +7,5 @@ import ../../lib/call-package.nix (
callSpectrumPackage ../make-vm.nix {} {
type = "nix";
run = lib.getExe foot;
+ runClosure = [ foot ];
}) (_: {})
--
2.54.0
^ permalink raw reply related [flat|nested] 19+ messages in thread
* [PATCH optional] linux: use 6.18 for generic images
2026-06-26 18:55 [PATCH 0/8] refresh nixpkgs for Linux 7.1 colbyt
` (7 preceding siblings ...)
2026-06-26 18:55 ` [PATCH 8/8] vm-lib: allow app VMs to name closure roots colbyt
@ 2026-06-26 18:55 ` colbyt
2026-07-02 13:42 ` Alyssa Ross
2026-07-02 12:03 ` [PATCH 0/8] refresh nixpkgs for Linux 7.1 Alyssa Ross
9 siblings, 1 reply; 19+ messages in thread
From: colbyt @ 2026-06-26 18:55 UTC (permalink / raw)
To: devel; +Cc: colbyt
Keep the generic rootfs, app VM, net VM, and installer on the linux_6_18
package set after updating nixpkgs.
This is an optional conservative variant for deployments that should stay
on the Linux 6.18 LTS line instead of following linux_latest to Linux
7.1.1. With the new nixpkgs pin, that keeps the LTS track while updating
from Linux 6.18.2 to Linux 6.18.36.
Tested with the full integration suite on Linux 6.18.36.
Signed-off-by: colbyt <colby@colbyt.com>
---
host/rootfs/default.nix | 4 ++--
img/app/default.nix | 4 ++--
release/installer/configuration.nix | 2 +-
vm/sys/net/default.nix | 4 ++--
4 files changed, 7 insertions(+), 7 deletions(-)
diff --git a/host/rootfs/default.nix b/host/rootfs/default.nix
index 6bfeefb..334f5de 100644
--- a/host/rootfs/default.nix
+++ b/host/rootfs/default.nix
@@ -4,7 +4,7 @@
import ../../lib/call-package.nix (
{ callSpectrumPackage, config, spectrum-build-tools
-, src, pkgsMusl, inkscape, linuxPackagesFor, linux_latest, xorg
+, src, pkgsMusl, inkscape, linuxPackagesFor, linux_6_18, xorg
}:
pkgsMusl.callPackage (
@@ -51,7 +51,7 @@ let
system.stateVersion = trivial.release;
});
- kernel = linux_latest;
+ kernel = linux_6_18;
appvm = callSpectrumPackage ../../img/app { inherit (foot) terminfo; };
netvm = callSpectrumPackage ../../vm/sys/net { inherit (foot) terminfo; };
diff --git a/img/app/default.nix b/img/app/default.nix
index 71e6fa0..72d618b 100644
--- a/img/app/default.nix
+++ b/img/app/default.nix
@@ -5,7 +5,7 @@ import ../../lib/call-package.nix (
{ spectrum-app-tools, spectrum-build-tools, src, terminfo
, lib, appimageTools, buildFHSEnv, runCommand, stdenvNoCC, writeClosure
, erofs-utils, jq, s6-rc, util-linux, xorg
-, cacert, linux_latest
+, cacert, linux_6_18
}:
let
@@ -21,7 +21,7 @@ let
else
stdenvNoCC.hostPlatform.linux-kernel.target;
- kernel = (linux_latest.override {
+ kernel = (linux_6_18.override {
structuredExtraConfig = with lib.kernel; {
DRM_FBDEV_EMULATION = lib.mkForce no;
EROFS_FS = yes;
diff --git a/release/installer/configuration.nix b/release/installer/configuration.nix
index 3f9ef24..415e5e9 100644
--- a/release/installer/configuration.nix
+++ b/release/installer/configuration.nix
@@ -14,7 +14,7 @@ in
boot.kernelParams = [ "udev.log_priority=5" ];
boot.initrd.verbose = false;
- boot.kernelPackages = pkgs.linuxPackages_latest;
+ boot.kernelPackages = pkgs.linuxPackagesFor pkgs.linux_6_18;
boot.plymouth.enable = true;
boot.plymouth.logo = pkgs.callPackage (
diff --git a/vm/sys/net/default.nix b/vm/sys/net/default.nix
index a722b02..fc7885e 100644
--- a/vm/sys/net/default.nix
+++ b/vm/sys/net/default.nix
@@ -7,7 +7,7 @@ pkgsMusl.callPackage (
{ lib, stdenvNoCC, nixos, runCommand, writeClosure
, erofs-utils, jq, s6-rc, util-linux, xorg
-, busybox, dbus, execline, iwd, kmod, linuxPackagesFor, linux_latest
+, busybox, dbus, execline, iwd, kmod, linuxPackagesFor, linux_6_18
, mdevd, nftables, s6, s6-linux-init, spectrum-driver-tools, xdp-tools
}:
@@ -27,7 +27,7 @@ let
else
stdenvNoCC.hostPlatform.linux-kernel.target;
- kernel = (linux_latest.override {
+ kernel = (linux_6_18.override {
structuredExtraConfig = with lib.kernel; {
DRM_FBDEV_EMULATION = lib.mkForce no;
EROFS_FS = yes;
--
2.54.0
^ permalink raw reply related [flat|nested] 19+ messages in thread
* Re: [PATCH 3/8] pkgs/skaware: vendor backported patches
2026-06-26 18:55 ` [PATCH 3/8] pkgs/skaware: vendor backported patches colbyt
@ 2026-07-02 11:53 ` Alyssa Ross
0 siblings, 0 replies; 19+ messages in thread
From: Alyssa Ross @ 2026-07-02 11:53 UTC (permalink / raw)
To: colbyt; +Cc: devel
[-- Attachment #1: Type: text/plain, Size: 600 bytes --]
colbyt <colby@colbyt.com> writes:
> Two skaware backports were fetched from cgit patch endpoints. Those
> endpoints are not stable enough for package inputs: the same URL can
> return an unrelated patch, breaking the build before the VM can start.
>
> Keep the small upstream diffs in-tree instead. The package still
> applies the same s6 and mdevd fixes, and the comments next to each patch
> record the upstream commit IDs.
>
> Signed-off-by: colbyt <colby@colbyt.com>
This was hopefully taken care of by
https://spectrum-os.org/git/spectrum/commit/?id=e4562d4c7646fea3cbb7306ff9b7ff41154c75c3
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 227 bytes --]
^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: [PATCH 0/8] refresh nixpkgs for Linux 7.1
2026-06-26 18:55 [PATCH 0/8] refresh nixpkgs for Linux 7.1 colbyt
` (8 preceding siblings ...)
2026-06-26 18:55 ` [PATCH optional] linux: use 6.18 for generic images colbyt
@ 2026-07-02 12:03 ` Alyssa Ross
9 siblings, 0 replies; 19+ messages in thread
From: Alyssa Ross @ 2026-07-02 12:03 UTC (permalink / raw)
To: colbyt; +Cc: devel
[-- Attachment #1: Type: text/plain, Size: 1522 bytes --]
colbyt <colby@colbyt.com> writes:
> This series moves the default nixpkgs pin forward and fixes the build
> and runtime issues exposed on the generic Spectrum path. It lets the
> generic images follow linux_latest, which currently selects Linux 7.1.1.
>
> The changes are split by cause: aarch64-musl build fixes exposed by the
> pin bump, integrated skaware and GTK backports, Cloud Hypervisor 52.0
> with the local vhost-user GPU patchset rebased, the libfyaml pkg-config
> cleanup needed by AppStream, and the app VM closure-root fix for foot
> and Firefox.
>
> The Cloud Hypervisor update includes the crosvm SHMEM_MAP compatibility
> needed by the current crosvm GPU backend.
I have an update to current Nixpkgs staging-next in the work, that
should be ready to commit as soon as the staging cycle completes and
Nixpkgs unstable updates. staging-next currently contains a lot of
fixes that aren't in unstable, so by waiting a week or so for it we can
avoid the need for a lot of downstream workarounds. I'll post the patch
soon so you can try it out in advance, if you want. (Eventually we need
to not be going months without updating, but while it's been so long I
think waiting an extra week or so is okay, and I promise the gap was
because other good things were happening — I just can't say what they
might have been yet. ;)) So with that in mind I will pass on the update
patches, but I'll still try to go through and review, because I
think there's educational value to that.
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 227 bytes --]
^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: [PATCH 1/8] pkgs: fix aarch64-musl builds with current nixpkgs
2026-06-26 18:55 ` [PATCH 1/8] pkgs: fix aarch64-musl builds with current nixpkgs colbyt
@ 2026-07-02 12:18 ` Alyssa Ross
0 siblings, 0 replies; 19+ messages in thread
From: Alyssa Ross @ 2026-07-02 12:18 UTC (permalink / raw)
To: colbyt; +Cc: devel
[-- Attachment #1: Type: text/plain, Size: 2387 bytes --]
colbyt <colby@colbyt.com> writes:
> The newer nixpkgs pin exposes several aarch64-musl build issues in
> Spectrum dependencies.
>
> Normalize Python bootstrap outputs that install under usr/, patch the
> generated pyproject-build wrapper to include those paths, and keep the
> GnuTLS STARTTLS tests from observing a host /usr/bin/socat that is not
> on PATH.
>
> Also skip the exact psutil and mypy tests that depend on host network or
> unsandboxed root directory details. The remaining package test suites
> pass with those exact deselections.
>
> Signed-off-by: colbyt <colby@colbyt.com>
Unsandboxed builds on Linux are not commonly used, but they are still
supposed to work, so these fixes perhaps belong in upstream Nixpkgs.
They're unlikely to be specific to aarch64 or to musl. (You will likely
save yourself a lot of future pain if you can find a way to run your
builds sandboxed though — not many other people will encounter these
issues.)
> ---
> pkgs/overlay.nix | 105 +++++++++++++++++++++++++++++++++++++++++++++++
> 1 file changed, 105 insertions(+)
>
> diff --git a/pkgs/overlay.nix b/pkgs/overlay.nix
> index 3e3336e..66fea11 100644
> --- a/pkgs/overlay.nix
> +++ b/pkgs/overlay.nix
> @@ -4,12 +4,117 @@
> (final: super: {
> cloud-hypervisor = import ./cloud-hypervisor { inherit final super; };
>
> + coreutils = super.coreutils.overrideAttrs ({ postPatch ? "", ... }: (
> + final.lib.optionalAttrs
> + (super.stdenv.hostPlatform.isAarch64 && super.stdenv.hostPlatform.isMusl)
> + {
> + postPatch = postPatch + ''
> + # These locale-sensitive tests fail in the aarch64-musl bootstrap build.
> + for f in \
> + tests/cut/mb-non-utf8.sh \
> + tests/date/date-locale-hour.sh \
> + tests/dd/conv-case.sh \
> + tests/numfmt/mb-non-utf8.sh \
> + tests/paste/multi-byte.sh \
> + tests/sort/sort-h-thousands-sep.sh \
> + tests/sort/sort-month.sh
> + do
> + sed '2i echo Skipping aarch64-musl locale test && exit 77' -i "$f"
> + done
> + '';
> + }
> + ));
I don't know what's up with this one though. I build on aarch64 with
musl regularly and have never seen this problem. Would be interesting
to know if it reproduces with sandboxing enabled.
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 227 bytes --]
^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: [PATCH 4/8] pkgs/gtk3: skip integrated Wayland backport
2026-06-26 18:55 ` [PATCH 4/8] pkgs/gtk3: skip integrated Wayland backport colbyt
@ 2026-07-02 12:19 ` Alyssa Ross
0 siblings, 0 replies; 19+ messages in thread
From: Alyssa Ross @ 2026-07-02 12:19 UTC (permalink / raw)
To: colbyt; +Cc: devel
[-- Attachment #1: Type: text/plain, Size: 1364 bytes --]
colbyt <colby@colbyt.com> writes:
> The updated nixpkgs pin already contains the GTK Wayland backport carried
> by Spectrum.
>
> Drop the local patch from the package override so the build does not try
> to apply an already-integrated change.
>
> Signed-off-by: colbyt <colby@colbyt.com>
> ---
> pkgs/gtk3/default.nix | 4 ++--
> 1 file changed, 2 insertions(+), 2 deletions(-)
>
> diff --git a/pkgs/gtk3/default.nix b/pkgs/gtk3/default.nix
> index 72445c9..47c5a14 100644
> --- a/pkgs/gtk3/default.nix
> +++ b/pkgs/gtk3/default.nix
> @@ -3,8 +3,8 @@
>
> import ../../lib/overlay-package.nix [ "gtk3" ] ({ final, super }:
>
> -super.gtk3.overrideAttrs ({ patches ? [], ... }: {
> - patches = patches ++ [
> +super.gtk3.overrideAttrs ({ patches ? [], version, ... }: {
> + patches = patches ++ final.lib.optionals (final.lib.versionOlder version "3.24.52") [
There shouldn't be any need for version checks like this, because we
don't support building with older Nixpkgs versions. Once we've
upgraded, backports like this can just be deleted. (The goal is to be
applying 0 patches in Spectrum!)
> (final.fetchpatch {
> url = "https://gitlab.gnome.org/GNOME/gtk/-/commit/8569e206badbee1b27ff0e27316391b8d8c3f987.patch";
> hash = "sha256-OdBhCGtz+3HS8LRhp+GCj3dL4pntybiI9b3A3kc5+OY=";
> --
> 2.54.0
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 227 bytes --]
^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: [PATCH 8/8] vm-lib: allow app VMs to name closure roots
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
0 siblings, 1 reply; 19+ messages in thread
From: Alyssa Ross @ 2026-07-02 13:38 UTC (permalink / raw)
To: colbyt; +Cc: devel
[-- Attachment #1: Type: text/plain, Size: 555 bytes --]
colbyt <colby@colbyt.com> writes:
> make-vm copies the closure of the run path into the image.
>
> For app VMs that use lib.getExe, that can miss files from the package
> output that owns the executable. Allow callers to pass explicit closure
> roots, and use the package derivations for the foot and Firefox app VMs.
>
> Signed-off-by: colbyt <colby@colbyt.com>
Can you give an example of something it misses? If a store path depends
on paths not in its closure, that's likely a packaging bug (outside of
specific exceptions like /run/opengl-driver).
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 227 bytes --]
^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: [PATCH optional] linux: use 6.18 for generic images
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
0 siblings, 1 reply; 19+ messages in thread
From: Alyssa Ross @ 2026-07-02 13:42 UTC (permalink / raw)
To: colbyt; +Cc: devel
[-- Attachment #1: Type: text/plain, Size: 1231 bytes --]
colbyt <colby@colbyt.com> writes:
> Keep the generic rootfs, app VM, net VM, and installer on the linux_6_18
> package set after updating nixpkgs.
>
> This is an optional conservative variant for deployments that should stay
> on the Linux 6.18 LTS line instead of following linux_latest to Linux
> 7.1.1. With the new nixpkgs pin, that keeps the LTS track while updating
> from Linux 6.18.2 to Linux 6.18.36.
>
> Tested with the full integration suite on Linux 6.18.36.
>
> Signed-off-by: colbyt <colby@colbyt.com>
In Spectrum proper I'd like to stick to the latest stable kernels.
There are a few reasons for this:
• Backports, including security fixes, to older kernels are best-effort,
and sometimes end up getting missed.
• By working with newer kernels we catch regressions faster. The longer
it takes for a regression to be found, the more difficult it can be to
get it fixed (e.g. because there's a higher chance somebody has
started depending on the new behaviour).
• New features from new kernels!
Naturally, some specialized deployments might still prefer to pin a
kernel version, and Spectrum should facilitate this as long as it
doesn't cause undue maintenance overhead.
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 227 bytes --]
^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: [PATCH optional] linux: use 6.18 for generic images
2026-07-02 13:42 ` Alyssa Ross
@ 2026-07-02 23:20 ` colby
0 siblings, 0 replies; 19+ messages in thread
From: colby @ 2026-07-02 23:20 UTC (permalink / raw)
To: Alyssa Ross; +Cc: devel
Awesome -- for my purposes I only needed a current kernel, I just was doing that out of perceived consideration, since I was sending a major nix update and going to the newest kernel.
All of those sets are just all the things I had to do to get to nixlatest and boot native apple devices, in case you didn't have any of those update patches on your local.
On Thursday, July 2nd, 2026 at 7:28 AM, Alyssa Ross <hi@alyssa.is> wrote:
> colbyt <colby@colbyt.com> writes:
>
> > Keep the generic rootfs, app VM, net VM, and installer on the linux_6_18
> > package set after updating nixpkgs.
> >
> > This is an optional conservative variant for deployments that should stay
> > on the Linux 6.18 LTS line instead of following linux_latest to Linux
> > 7.1.1. With the new nixpkgs pin, that keeps the LTS track while updating
> > from Linux 6.18.2 to Linux 6.18.36.
> >
> > Tested with the full integration suite on Linux 6.18.36.
> >
> > Signed-off-by: colbyt <colby@colbyt.com>
>
> In Spectrum proper I'd like to stick to the latest stable kernels.
> There are a few reasons for this:
>
> • Backports, including security fixes, to older kernels are best-effort,
> and sometimes end up getting missed.
> • By working with newer kernels we catch regressions faster. The longer
> it takes for a regression to be found, the more difficult it can be to
> get it fixed (e.g. because there's a higher chance somebody has
> started depending on the new behaviour).
> • New features from new kernels!
>
> Naturally, some specialized deployments might still prefer to pin a
> kernel version, and Spectrum should facilitate this as long as it
> doesn't cause undue maintenance overhead.
>
^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: [PATCH 8/8] vm-lib: allow app VMs to name closure roots
2026-07-02 13:38 ` Alyssa Ross
@ 2026-07-02 23:40 ` colby
2026-07-03 14:02 ` Alyssa Ross
0 siblings, 1 reply; 19+ messages in thread
From: colby @ 2026-07-02 23:40 UTC (permalink / raw)
To: Alyssa Ross; +Cc: devel
“Miss files” was imprecise.
The issue I hit was not a store path depending on something outside its closure. It was that `run` can be an executable subpath from `lib.getExe`, e.g.
/nix/store/...-firefox-.../bin/firefox
and `writeClosure`/`exportReferencesGraph` wants store paths, not arbitrary subpaths. In that case the graph root should be the package output path (`/nix/store/...-firefox-...`) while `fs/run` should still point at the executable.
So the intent of `runClosure` is to decouple “what should be executed” from “which store path(s) should seed the image closure.” For the current app VMs,
`run = lib.getExe firefox` / `lib.getExe foot`, while `runClosure = [ firefox ]` keeps the closure root as a store output.
The current patches were pragmatic unblockers for the Asahi/nix-portable build environment where I was running with `--option sandbox false`. The failures I saw, especially the Python bootstrap `usr/` output shape, GnuTLS probing `/usr/bin/socat`, the mypy test observing the unsandboxed build root, and the libfyaml `.pc` `none required` tokens, are better treated as Nixpkgs issues or temporary overlay workarounds for this pin.
I’ll try to split them mentally that way:
- keep only the Spectrum-specific build/runtime changes in the Spectrum series;
- either upstream the package fixes to Nixpkgs or carry them as clearly marked temporary pin workarounds;
I'll also try to get the builder onto sandboxed builds so I stop finding the uncommon unsandboxed-only failures first.
Thanks for your patience.
On Thursday, July 2nd, 2026 at 7:27 AM, Alyssa Ross <hi@alyssa.is> wrote:
> colbyt <colby@colbyt.com> writes:
>
> > make-vm copies the closure of the run path into the image.
> >
> > For app VMs that use lib.getExe, that can miss files from the package
> > output that owns the executable. Allow callers to pass explicit closure
> > roots, and use the package derivations for the foot and Firefox app VMs.
> >
> > Signed-off-by: colbyt <colby@colbyt.com>
>
> Can you give an example of something it misses? If a store path depends
> on paths not in its closure, that's likely a packaging bug (outside of
> specific exceptions like /run/opengl-driver).
>
^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: [PATCH 8/8] vm-lib: allow app VMs to name closure roots
2026-07-02 23:40 ` colby
@ 2026-07-03 14:02 ` Alyssa Ross
0 siblings, 0 replies; 19+ messages in thread
From: Alyssa Ross @ 2026-07-03 14:02 UTC (permalink / raw)
To: colby; +Cc: devel
[-- Attachment #1: Type: text/plain, Size: 3079 bytes --]
colby@colbyt.com writes:
> “Miss files” was imprecise.
>
> The issue I hit was not a store path depending on something outside its closure. It was that `run` can be an executable subpath from `lib.getExe`, e.g.
>
> /nix/store/...-firefox-.../bin/firefox
>
> and `writeClosure`/`exportReferencesGraph` wants store paths, not arbitrary subpaths. In that case the graph root should be the package output path (`/nix/store/...-firefox-...`) while `fs/run` should still point at the executable.
My understanding is that writeClosure and exportReferencesGraph are
supposed to be fine with being given subpaths of store paths, and will
just treat it as if they were given the root of the store path. A
couple of years ago this stopped working, but it was treated as a bug
and my PR restoring the previous behaviour was accepted:
https://github.com/NixOS/nix/pull/10549
You're not using a very old version of Nix that doesn't have that fix,
are you?
> So the intent of `runClosure` is to decouple “what should be executed” from “which store path(s) should seed the image closure.” For the current app VMs,
> `run = lib.getExe firefox` / `lib.getExe foot`, while `runClosure = [ firefox ]` keeps the closure root as a store output.
>
> The current patches were pragmatic unblockers for the Asahi/nix-portable build environment where I was running with `--option sandbox false`. The failures I saw, especially the Python bootstrap `usr/` output shape, GnuTLS probing `/usr/bin/socat`, the mypy test observing the unsandboxed build root, and the libfyaml `.pc` `none required` tokens, are better treated as Nixpkgs issues or temporary overlay workarounds for this pin.
>
> I’ll try to split them mentally that way:
> - keep only the Spectrum-specific build/runtime changes in the Spectrum series;
> - either upstream the package fixes to Nixpkgs or carry them as clearly marked temporary pin workarounds;
>
> I'll also try to get the builder onto sandboxed builds so I stop finding the uncommon unsandboxed-only failures first.
>
> Thanks for your patience.
That sounds right to me. We try to make sure changes are upstreamed as
far as possible — maximum benefit for all users of the upstream project,
and shares maintenance beyond just Spectrum's limited capacity.
Thanks again for all your enthusiasm and effort!
>
> On Thursday, July 2nd, 2026 at 7:27 AM, Alyssa Ross <hi@alyssa.is> wrote:
>
>> colbyt <colby@colbyt.com> writes:
>>
>> > make-vm copies the closure of the run path into the image.
>> >
>> > For app VMs that use lib.getExe, that can miss files from the package
>> > output that owns the executable. Allow callers to pass explicit closure
>> > roots, and use the package derivations for the foot and Firefox app VMs.
>> >
>> > Signed-off-by: colbyt <colby@colbyt.com>
>>
>> Can you give an example of something it misses? If a store path depends
>> on paths not in its closure, that's likely a packaging bug (outside of
>> specific exceptions like /run/opengl-driver).
>>
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 227 bytes --]
^ permalink raw reply [flat|nested] 19+ messages in thread
end of thread, other threads:[~2026-07-03 14:02 UTC | newest]
Thread overview: 19+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
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 ` [PATCH 6/8] pkgs/cloud-hypervisor: update GPU patchset to v52 colbyt
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
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).