diff --git a/.gitignore b/.gitignore index 90acb92..4812d58 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,2 @@ result -/testvm* -/target -/micro-activate .direnv/ diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 0000000..a1452cd --- /dev/null +++ b/.gitmodules @@ -0,0 +1,9 @@ +[submodule "muvm"] + path = muvm + url = https://github.com/valpackett/muvm +[submodule "libkrun"] + path = libkrun + url = https://github.com/containers/libkrun +[submodule "libkrunfw"] + path = libkrunfw + url = https://github.com/valpackett/libkrunfw diff --git a/README.md b/README.md index e98d7df..86e5096 100644 --- a/README.md +++ b/README.md @@ -21,19 +21,6 @@ This will start an interactive bash session inside the microVM. nix run '.#munix' -- testvm fastfetch ``` -**Create a custom VM:** - -Use the template to bootstrap a new munix project: - -```bash -mkdir my-vm && cd my-vm -nix flake init -t 'git+https://git.clan.lol/clan/munix#musictest' -git init && git add flake.nix -nix run -``` - -This creates a `flake.nix` with a music player demo (MPD + Euphonica). Edit the module to customize your VM. - ## munix Options - `--uid UID`, `-u UID` - Set microVM UID (default: 1337) @@ -68,3 +55,5 @@ PATH=$PWD/muvm/target/release:$PATH ./munix testvm - For Wayland: `XDG_RUNTIME_DIR` and `WAYLAND_DISPLAY` set ## Known Issues + +- **PipeWire audio**: Not yet working. diff --git a/devShells/default.nix b/devShells/default.nix index c288f30..9cc518d 100644 --- a/devShells/default.nix +++ b/devShells/default.nix @@ -1,49 +1,16 @@ -{ - mkShell, - lib, - systemd, - cargo, - rust-analyzer, - rustfmt, - passt, - bubblewrap, - libkrun, - muvm, - sidebus-broker, - wl-cross-domain-proxy, - wl-backdrop, - pkgs, -}: +{ mkShell, lib, systemd, cargo, rust-analyzer, rustfmt, passt, bubblewrap, libkrun, muvm }: let - projects = [ - libkrun - muvm - ]; -in -mkShell { + projects = [ libkrun muvm ]; +in mkShell { MUVM_UDEVD_PATH = "${systemd}/lib/systemd/systemd-udevd"; nativeBuildInputs = lib.concatMap (pkg: pkg.nativeBuildInputs) projects; - buildInputs = - (lib.concatMap (pkg: pkg.buildInputs) projects) - ++ [ - # virglrenderer - cargo - rust-analyzer - rustfmt - passt - bubblewrap - sidebus-broker - wl-cross-domain-proxy - wl-backdrop - ] - ++ (with pkgs; [ - meson - wayland - wayland-protocols - wayland-scanner - cairo - libgbm - ]); - # Enough things to compile wl-cross-domain-proxy, muvm, etc. in development + buildInputs = (lib.concatMap (pkg: pkg.buildInputs) projects) ++ [ + # virglrenderer + cargo + rust-analyzer + rustfmt + passt + bubblewrap + ]; } diff --git a/flake.lock b/flake.lock index 234a180..d60e81e 100644 --- a/flake.lock +++ b/flake.lock @@ -1,66 +1,48 @@ { "nodes": { - "flake-parts": { + "flake-utils": { "inputs": { - "nixpkgs-lib": [ - "nixpkgs" - ] + "systems": "systems" }, "locked": { - "lastModified": 1769996383, - "narHash": "sha256-AnYjnFWgS49RlqX7LrC4uA+sCCDBj0Ry/WOJ5XWAsa0=", - "owner": "hercules-ci", - "repo": "flake-parts", - "rev": "57928607ea566b5db3ad13af0e57e921e6b12381", + "lastModified": 1731533236, + "narHash": "sha256-l0KFg5HjrsfsO/JpG+r7fRrqm12kzFHyUHqHCVpMMbI=", + "owner": "numtide", + "repo": "flake-utils", + "rev": "11707dc2f618dd54ca8739b309ec4fc024de578b", "type": "github" }, "original": { - "owner": "hercules-ci", - "repo": "flake-parts", + "owner": "numtide", + "repo": "flake-utils", "type": "github" } }, - "libkrun-src": { - "flake": false, + "flake-utils_2": { + "inputs": { + "systems": "systems_2" + }, "locked": { - "lastModified": 1772170018, - "narHash": "sha256-pi4Mrx9wFE8zT8lx+0su2bP1tTkJBh5FaGNQjAFUAx4=", - "owner": "valpackett", - "repo": "libkrun", - "rev": "eeafbc55379b60379414168e7a22d5f95b73d7a0", + "lastModified": 1710146030, + "narHash": "sha256-SZ5L6eA7HJ/nmkzGG7/ISclqe6oZdOZTNoesiInkXPQ=", + "owner": "numtide", + "repo": "flake-utils", + "rev": "b1d9ab70662946ef0850d488da1c9019f3a9752a", "type": "github" }, "original": { - "owner": "valpackett", - "repo": "libkrun", - "rev": "eeafbc55379b60379414168e7a22d5f95b73d7a0", - "type": "github" - } - }, - "muvm-src": { - "flake": false, - "locked": { - "lastModified": 1772176363, - "narHash": "sha256-aSWulv3ml4XmMYnFOkZCd2YBLIY0Rr8CUHK1NDYk5jw=", - "owner": "valpackett", - "repo": "muvm", - "rev": "c68742bcedb96deb6f23ed5a83188022d1cdf71d", - "type": "github" - }, - "original": { - "owner": "valpackett", - "repo": "muvm", - "rev": "c68742bcedb96deb6f23ed5a83188022d1cdf71d", + "owner": "numtide", + "repo": "flake-utils", "type": "github" } }, "nixpkgs": { "locked": { - "lastModified": 1770197578, - "narHash": "sha256-AYqlWrX09+HvGs8zM6ebZ1pwUqjkfpnv8mewYwAo+iM=", + "lastModified": 1761672384, + "narHash": "sha256-o9KF3DJL7g7iYMZq9SWgfS1BFlNbsm6xplRjVlOCkXI=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "00c21e4c93d963c50d4c0c89bfa84ed6e0694df2", + "rev": "08dacfca559e1d7da38f3cf05f1f45ee9bfd213c", "type": "github" }, "original": { @@ -72,62 +54,64 @@ }, "root": { "inputs": { - "flake-parts": "flake-parts", - "libkrun-src": "libkrun-src", - "muvm-src": "muvm-src", + "flake-utils": "flake-utils", "nixpkgs": "nixpkgs", - "sidebus": "sidebus", - "wl-backdrop": "wl-backdrop" + "virtwl": "virtwl" } }, - "sidebus": { + "systems": { + "locked": { + "lastModified": 1681028828, + "narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=", + "owner": "nix-systems", + "repo": "default", + "rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e", + "type": "github" + }, + "original": { + "owner": "nix-systems", + "repo": "default", + "type": "github" + } + }, + "systems_2": { + "locked": { + "lastModified": 1681028828, + "narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=", + "owner": "nix-systems", + "repo": "default", + "rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e", + "type": "github" + }, + "original": { + "owner": "nix-systems", + "repo": "default", + "type": "github" + } + }, + "virtwl": { "inputs": { - "flake-parts": [ - "flake-parts" - ], + "flake-utils": "flake-utils_2", "nixpkgs": [ "nixpkgs" ] }, "locked": { - "lastModified": 1772183103, - "narHash": "sha256-9jbqBtaLUdOeT95PVUMz45JdUpVeJ25ZYZHEOQn9XsI=", - "ref": "main", - "rev": "c42eaef55440e2594677ede5279bd8c3eaf128f2", + "lastModified": 1758075582, + "narHash": "sha256-o2lpXQLaM9QcZVr+sAxvh83CqJW1QkFhfja6K40ndmA=", + "ref": "wip", + "rev": "5a5df73a11b2f6bf671a8fc89926ac993e0fbb78", "shallow": true, + "submodules": true, "type": "git", - "url": "https://git.clan.lol/clan/sidebus" + "url": "https://github.com/valpackett/wayland-proxy-virtwl" }, "original": { - "ref": "main", + "ref": "wip", "shallow": true, + "submodules": true, "type": "git", - "url": "https://git.clan.lol/clan/sidebus" - } - }, - "wl-backdrop": { - "inputs": { - "flake-parts": [ - "flake-parts" - ], - "nixpkgs": [ - "nixpkgs" - ] - }, - "locked": { - "lastModified": 1772781884, - "narHash": "sha256-epVLmAHnJi4EoZea5DUmxB3r6SPSMu3Nzki7JzbK0sA=", - "ref": "main", - "rev": "20e3910ef60aa627933a5d750b60cc3dcd0653cf", - "shallow": true, - "type": "git", - "url": "https://git.clan.lol/valpackett/wl-backdrop" - }, - "original": { - "ref": "main", - "shallow": true, - "type": "git", - "url": "https://git.clan.lol/valpackett/wl-backdrop" + "url": "https://github.com/valpackett/wayland-proxy-virtwl" } } }, diff --git a/flake.nix b/flake.nix index 6b9191b..c06aa16 100644 --- a/flake.nix +++ b/flake.nix @@ -5,142 +5,76 @@ }; inputs = { + self.submodules = true; nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable"; - - flake-parts.url = "github:hercules-ci/flake-parts"; - flake-parts.inputs.nixpkgs-lib.follows = "nixpkgs"; - - sidebus.url = "git+https://git.clan.lol/clan/sidebus?shallow=1&ref=main"; - sidebus.inputs.nixpkgs.follows = "nixpkgs"; - sidebus.inputs.flake-parts.follows = "flake-parts"; - - wl-backdrop.url = "git+https://git.clan.lol/valpackett/wl-backdrop?shallow=1&ref=main"; - wl-backdrop.inputs.nixpkgs.follows = "nixpkgs"; - wl-backdrop.inputs.flake-parts.follows = "flake-parts"; - - # To override with local checkouts during development, use the --override-input CLI flag! - muvm-src = { - url = "github:valpackett/muvm/c68742bcedb96deb6f23ed5a83188022d1cdf71d"; # v0.5.0+custom-init+dbus - flake = false; - }; - libkrun-src = { - url = "github:valpackett/libkrun/eeafbc55379b60379414168e7a22d5f95b73d7a0"; # PR #558 (map permission fix) + D-Bus WIP - flake = false; - }; - # libkrunfw-src = { - # url = "github:containers/libkrunfw/20484a2e60290acb74c43ccfd6e1ea4caf41d470"; # v5.1.0 - # flake = false; - # }; + # nixpkgs.url = "git+https://github.com/valpackett/nixpkgs?shallow=1&submodules=1&ref=.."; + flake-utils.url = "github:numtide/flake-utils"; + virtwl.url = "git+https://github.com/valpackett/wayland-proxy-virtwl?shallow=1&submodules=1&ref=wip"; + virtwl.inputs.nixpkgs.follows = "nixpkgs"; }; - outputs = - inputs@{ - self, - nixpkgs, - flake-parts, - sidebus, - wl-backdrop, - muvm-src, - libkrun-src, - # libkrunfw-src, - ... - }: - flake-parts.lib.mkFlake { inherit inputs; } { - systems = [ - "x86_64-linux" - "aarch64-linux" + outputs = { self, nixpkgs, flake-utils, virtwl, ... }: { + nixosModules.testvm = nixpkgs.lib.modules.importApply ./nixosModules/testvm.nix { inherit virtwl; }; + nixosModules.default = nixpkgs.lib.modules.importApply ./nixosModules/default.nix { inherit self virtwl; }; + + nixosConfigurations.testvm-x86_64 = nixpkgs.lib.nixosSystem { + system = "x86_64-linux"; + modules = [ + self.nixosModules.default + self.nixosModules.testvm + { nixpkgs.config.allowUnfree = true; } ]; - - flake = { - nixosModules.testvm = nixpkgs.lib.modules.importApply ./nixosModules/testvm.nix { }; - nixosModules.default = nixpkgs.lib.modules.importApply ./nixosModules/default.nix { - inherit self; - }; - - templates.musictest = { - description = "Music player demo VM with MPD and Euphonica"; - path = ./templates/musictest; - }; - - nixosConfigurations.testvm-x86_64 = nixpkgs.lib.nixosSystem { - system = "x86_64-linux"; - modules = [ - self.nixosModules.default - self.nixosModules.testvm - { nixpkgs.config.allowUnfree = true; } - ]; - }; - - nixosConfigurations.testvm-aarch64 = nixpkgs.lib.nixosSystem { - system = "aarch64-linux"; - modules = [ - self.nixosModules.default - self.nixosModules.testvm - { nixpkgs.config.allowUnfree = true; } - ]; - }; - }; - - perSystem = - { - pkgs, - system, - self', - ... - }: - { - _module.args.pkgs = import nixpkgs { - inherit system; - config.allowUnfree = true; - }; - - checks = - (pkgs.lib.mapAttrs' (n: pkgs.lib.nameValuePair "package-${n}") self'.packages) - // (pkgs.lib.mapAttrs' (n: pkgs.lib.nameValuePair "devShell-${n}") self'.devShells) - // (pkgs.lib.optionalAttrs (system == "x86_64-linux") { - nixos-testvm = self.nixosConfigurations.testvm-x86_64.config.system.build.toplevel; - }) - // (pkgs.lib.optionalAttrs (system == "aarch64-linux") { - nixos-testvm = self.nixosConfigurations.testvm-aarch64.config.system.build.toplevel; - }); - - packages = { - # Packages support variant parameter: null (default), "sev", or "tdx" - # To build a variant: packages.libkrunfw.override { variant = "sev"; } - libkrunfw = pkgs.callPackage ./packages/libkrunfw { - # libkrunfw-src = libkrunfw-src; - }; - - libkrun = pkgs.callPackage ./packages/libkrun { - libkrunfw = self'.packages.libkrunfw; - libkrun-src = libkrun-src; - }; - - mesa = pkgs.callPackage ./packages/mesa { }; - - muvm = pkgs.callPackage ./packages/muvm { - libkrun = self'.packages.libkrun; - muvm-src = muvm-src; - }; - - munix = pkgs.callPackage ./packages/munix { - mesa = self'.packages.mesa; - muvm = self'.packages.muvm; - wl-cross-domain-proxy = self'.packages.wl-cross-domain-proxy; - wl-backdrop = wl-backdrop.packages.${system}.wl-backdrop; - sidebus-broker = sidebus.packages.${system}.sidebus-broker; - }; - - wl-cross-domain-proxy = pkgs.callPackage ./packages/wl-cross-domain-proxy { }; - }; - - devShells.default = pkgs.callPackage ./devShells { - libkrun = self'.packages.libkrun; - muvm = self'.packages.muvm; - wl-cross-domain-proxy = self'.packages.wl-cross-domain-proxy; - wl-backdrop = wl-backdrop.packages.${system}.wl-backdrop; - sidebus-broker = sidebus.packages.${system}.sidebus-broker; - }; - }; }; + + nixosConfigurations.testvm-aarch64 = nixpkgs.lib.nixosSystem { + system = "aarch64-linux"; + modules = [ + self.nixosModules.default + self.nixosModules.testvm + { nixpkgs.config.allowUnfree = true; } + ]; + }; + } // flake-utils.lib.eachSystem [ "x86_64-linux" "aarch64-linux" ] (system: + let + pkgs = import nixpkgs { + inherit system; + config.allowUnfree = true; + }; + in { + + checks = + (pkgs.lib.mapAttrs' (n: pkgs.lib.nameValuePair "package-${n}") self.packages.${system}) + // (pkgs.lib.mapAttrs' (n: pkgs.lib.nameValuePair "devShell-${n}") self.devShells.${system}) + // (pkgs.lib.optionalAttrs (system == "x86_64-linux") { + nixos-testvm = self.nixosConfigurations.testvm-x86_64.config.system.build.toplevel; + }) + // (pkgs.lib.optionalAttrs (system == "aarch64-linux") { + nixos-testvm = self.nixosConfigurations.testvm-aarch64.config.system.build.toplevel; + }); + + packages = { + # Packages support variant parameter: null (default), "sev", or "tdx" + # To build a variant: packages.libkrunfw.override { variant = "sev"; } + libkrunfw = pkgs.callPackage ./packages/libkrunfw { }; + + libkrun = pkgs.callPackage ./packages/libkrun { + libkrunfw = self.packages.${system}.libkrunfw; + }; + + mesa = pkgs.callPackage ./packages/mesa { }; + + muvm = pkgs.callPackage ./packages/muvm { + libkrun = self.packages.${system}.libkrun; + }; + + munix = pkgs.callPackage ./packages/munix { + muvm = self.packages.${system}.muvm; + }; + }; + + devShells.default = pkgs.callPackage ./devShells { + libkrun = self.packages.${system}.libkrun; + muvm = self.packages.${system}.muvm; + }; + }); } diff --git a/libkrun b/libkrun new file mode 160000 index 0000000..72b8b08 --- /dev/null +++ b/libkrun @@ -0,0 +1 @@ +Subproject commit 72b8b0870c3ecad0388f52150a68f79083fcc86f diff --git a/libkrunfw b/libkrunfw new file mode 160000 index 0000000..4b98077 --- /dev/null +++ b/libkrunfw @@ -0,0 +1 @@ +Subproject commit 4b98077866355ecfed46781ab6143d21127bf977 diff --git a/micro-activate.rs b/micro-activate.rs deleted file mode 100644 index 765fb30..0000000 --- a/micro-activate.rs +++ /dev/null @@ -1,155 +0,0 @@ -use std::os::raw::{c_char, c_int, c_ulong, c_void}; -use std::os::unix::ffi::OsStrExt; -use std::os::unix::process::CommandExt; - -const MS_RDONLY: c_ulong = 0x01; -const MS_NOSUID: c_ulong = 0x02; -const MS_NODEV: c_ulong = 0x04; -const MS_RELATIME: c_ulong = 0x200000; -const MS_STRICTATIME: c_ulong = 0x1000000; - -const CLONE_NEWTIME: c_int = 0x80; - -unsafe extern "C" { - fn mount( - src: *const c_char, - target: *const c_char, - fstype: *const c_char, - flags: c_ulong, - data: *const c_void, - ) -> c_int; - fn getrandom(buf: *mut u8, buflen: usize, flags: u32) -> c_int; - fn unshare(flags: c_int) -> c_int; -} - -fn gen_machine_id() -> String { - use std::fmt::Write as _; - let mut bytes: [u8; 16] = [0; 16]; - if unsafe { getrandom(bytes.as_mut_ptr(), 16, 0) } == -1 { - eprintln!("[micro-activate] getrandom failed!"); - } - let mut result = String::with_capacity(32); - for b in bytes { - let _ = write!(result, "{:02x}", b); - } - result -} - -fn parse_tmpfiles_line(line: &str) -> Option<(&str, &str)> { - // NOTE: does not support actual whitespace inside quotes - // (that's not gonna appear in these files we parse) - let mut it = line - .split_whitespace() - .map(|s| s.trim_start_matches('\'').trim_end_matches('\'')); - let instr = it.next()?; - if !instr.starts_with('L') { - return None; - } - let src = it.next()?; - let _ = it.next()?; - let _ = it.next()?; - let _ = it.next()?; - let _ = it.next()?; - let dst = it.next()?; - Some((src, dst)) -} - -fn link_tmpfiles(contents: &[u8]) -> Result<(), std::io::Error> { - for (src, dst) in str::from_utf8(contents) - .unwrap() - .lines() - .flat_map(parse_tmpfiles_line) - { - std::os::unix::fs::symlink(dst, src)?; - } - Ok(()) -} - -fn main() -> Result<(), std::io::Error> { - let closure = std::env::var("MICROVM_CLOSURE").unwrap(); - - // systemd really wants /run to be a mountpoint and will mount a tmpfs on its own - // if it's not already a mountpoint. Well, it's correct: reaching into virtiofs - // (which is what not-mounting would entail) for /run stuff is not great. - // - // Let's preserve the fixed passed-in files and set up the NixOS symlinks in the new mount. - let resolv_conf = std::fs::read("/run/resolv.conf")?; - let localtime = std::fs::read("/run/localtime")?; - assert_eq!( - unsafe { - mount( - c"tmpfs".as_ptr(), - c"/run".as_ptr(), - c"tmpfs".as_ptr(), - MS_NOSUID | MS_NODEV | MS_STRICTATIME, - std::ptr::null(), - ) - }, - 0 - ); - std::fs::write("/run/localtime", &localtime)?; - std::fs::write("/run/resolv.conf", &resolv_conf)?; - std::fs::write("/run/machine-id", &gen_machine_id())?; - std::fs::create_dir("/run/systemd")?; - std::os::unix::fs::symlink("/opt/systemd", "/run/systemd/system")?; - std::os::unix::fs::symlink(&closure, "/run/current-system")?; - if let Ok(tmp_graphics) = - std::fs::read(format!("{closure}/etc/tmpfiles.d/graphics-driver.conf")) - { - link_tmpfiles(&tmp_graphics)?; - } else { - eprintln!("[micro-activate] Could not find the closure's graphics-driver.conf!"); - } - - // We need the /etc metadata overlay not just for abstract correctness, but even just to - // allow the regular user to run systemctl (it doesn't like passwd being owned by non-root).. - let metadata_img = std::fs::read_link(format!("{closure}/etc-metadata-image")) - .expect("The closure must use an immutable /etc overlay!"); - let basedir = std::fs::read_link(format!("{closure}/etc-basedir")) - .expect("The closure must use an immutable /etc overlay!"); - let overlay_opts = std::ffi::CString::new(format!( - "redirect_dir=on,metacopy=on,lowerdir=/run/etc.meta::{}", - basedir.display() - )) - .unwrap(); - std::fs::create_dir("/run/etc.meta")?; - std::fs::remove_file("/etc")?; - std::fs::create_dir("/etc")?; - unsafe { - assert_eq!( - mount( - metadata_img.as_os_str().as_bytes().as_ptr() as *const c_char, - c"/run/etc.meta".as_ptr(), - c"erofs".as_ptr(), - MS_RDONLY | MS_NODEV | MS_NOSUID, - std::ptr::null(), - ), - 0 - ); - assert_eq!( - mount( - c"overlay".as_ptr(), - c"/etc".as_ptr(), - c"overlay".as_ptr(), - MS_NODEV | MS_NOSUID | MS_RELATIME, - overlay_opts.as_ptr() as *const c_void, - ), - 0 - ); - } - - if let Ok(offset) = std::env::var("BOOT_TIME_OFFSET") { - if unsafe { unshare(CLONE_NEWTIME) } != 0 { - eprintln!("[micro-activate] Could not unshare time!"); - } else { - std::fs::write( - "/proc/self/timens_offsets", - format!("monotonic {offset}\nboottime {offset}\n"), - )?; - } - } - - let mut args = std::env::args_os().skip(1); - let cmd = args.next().unwrap(); - Err(std::process::Command::new(cmd).args(args).exec()) -} diff --git a/munix b/munix index 619a38f..4c5e9c4 100755 --- a/munix +++ b/munix @@ -2,46 +2,19 @@ SCRIPT_PATH=$(dirname $(realpath -s $0)) MUVM_PATH=$(dirname $(which muvm)) PASST_PATH=$(dirname $(which passt)) -WL_PROXY_PATH=$(dirname $(which wl-cross-domain-proxy)) -WL_BACKDROP_PATH=$(dirname $(which wl-backdrop)) HOST_OPENGL_DRIVER=/run/opengl-driver -: "${MICROVM_DEFAULT_COMMAND:=bash}" -: "${MUNIX_SYSTEMD_UNITS:="${SCRIPT_PATH}/systemd"}" MICROVM_CLOSURE= MICROVM_COMMAND=() MICROVM_UID=1337 MICROVM_GID=1337 BWRAP_ARGS=() MUVM_ARGS=() -SIDEBUS_ARGS=() GPU=1 WAYLAND=1 PIPEWIRE=1 X11=0 -ENV_DEFAULTS=1 -USING_PUBLISH=0 export TMP=/tmp TMPDIR=/tmp TEMP=/tmp TEMPDIR=/tmp LC_ALL=C -if [ ! -e "$HOST_OPENGL_DRIVER" ]; then - HOST_OPENGL_DRIVER="$FALLBACK_OPENGL_DRIVER" -fi - -# A little bit cursed: pre-pass to relaunch with new env var.. -BG_COLOR= -pargs=() -while [ "$#" -gt 0 ]; do - case "$1" in - --bg-color) BG_COLOR="$2"; shift 2;; - --wl-backdrop-bin-dir) WL_BACKDROP_PATH="$2"; shift 2;; - *) pargs+=("$1"); shift;; - esac -done -if [ "$BG_COLOR" = "" ]; then - set -- "${pargs[@]}" -else - exec "$WL_BACKDROP_PATH/wl-backdrop" --background "$BG_COLOR" -- "$(readlink -f "$0")" "${pargs[@]}" -fi - while [ "$#" -gt 0 ]; do case "$1" in -u|--uid) MICROVM_UID="$2"; shift 2;; @@ -49,19 +22,15 @@ while [ "$#" -gt 0 ]; do --no-gpu) GPU=0; shift 1;; --no-wayland) WAYLAND=0; shift 1;; --no-pipewire) PIPEWIRE=0; shift 1;; - --no-env-defaults) ENV_DEFAULTS=0; shift 1;; --x11) X11=1; shift 1;; - -b|--bind) BWRAP_ARGS+=("--bind" "$2" "$3"); SIDEBUS_ARGS+=("--path-mapping" "$3=$2"); shift 3;; - --ro-bind) BWRAP_ARGS+=("--ro-bind" "$2" "$3"); SIDEBUS_ARGS+=("--path-mapping" "$3=$2"); shift 3;; - -e|--expose) BWRAP_ARGS+=("--bind" "$2" "$2"); SIDEBUS_ARGS+=("--path-mapping" "$2=$2"); shift 2;; - --ro-expose) BWRAP_ARGS+=("--ro-bind" "$2" "$2"); SIDEBUS_ARGS+=("--path-mapping" "$2=$2"); shift 2;; - -p|--publish) USING_PUBLISH=1; MUVM_ARGS+=("--publish=$2"); shift 2;; + --bind) BWRAP_ARGS+=("--bind" "$2" "$3"); shift 3;; + --ro-bind) BWRAP_ARGS+=("--ro-bind" "$2" "$3"); shift 3;; + --expose) BWRAP_ARGS+=("--bind" "$2" "$2"); shift 2;; + --ro-expose) BWRAP_ARGS+=("--ro-bind" "$2" "$2"); shift 2;; --host-opengl-driver) HOST_OPENGL_DRIVER="$2"; shift 2;; --munix-bin-dir) SCRIPT_PATH="$2"; shift 2;; --muvm-bin-dir) MUVM_PATH="$2"; shift 2;; --passt-bin-dir) PASST_PATH="$2"; shift 2;; - --wl-proxy-bin-dir) WL_PROXY_PATH="$2"; shift 2;; - --wl-backdrop-bin-dir) shift 2;; --) shift 1; MICROVM_COMMAND+=("$@"); break;; -*) echo "munix: unknown option: $1" >&2; exit 1;; *) @@ -79,36 +48,11 @@ if [ "$MICROVM_CLOSURE" = "" ]; then exit 1 fi -if [ "$MUVM_PATH" = "" ]; then - echo "munix: muvm not found, provide a --muvm-bin-dir or fix \$PATH" >&2 - exit 1 -fi - -if [ "$PASST_PATH" = "" ]; then - echo "munix: passt not found, provide a --passt-bin-dir or fix \$PATH" >&2 - exit 1 -fi - -if [ "$WL_PROXY_PATH" = "" ]; then - echo "munix: wl-cross-domain-proxy not found, provide a --wl-proxy-bin-dir or fix \$PATH" >&2 - exit 1 -fi - -if [ "$WL_BACKDROP_PATH" = "" ]; then - echo "munix: wl-backdrop not found, provide a --wl-backdrop-bin-dir or fix \$PATH" >&2 - exit 1 -fi - -if [ ! -e "$HOST_OPENGL_DRIVER" ]; then - echo "munix: host graphics driver not found, provide a --host-opengl-driver" >&2 - exit 1 -fi - # Resolve symlinks automatically MICROVM_CLOSURE=$(realpath "$MICROVM_CLOSURE") if [ ${#MICROVM_COMMAND[@]} -eq 0 ]; then - MICROVM_COMMAND=("$MICROVM_DEFAULT_COMMAND") + MICROVM_COMMAND=("bash") fi if [ "$GPU" -eq 1 ]; then @@ -129,7 +73,7 @@ if [ "$GPU" -eq 1 ]; then driver_mod="$(readlink "$driver_link")" driver_name="${driver_mod##*/}" case "$driver_name" in - amdgpu|msm_dpu) # TODO: i915 + amdgpu|msm) # TODO: i915 echo "munix: ${card##*/} gpu driver is '$driver_name', using vdrm" >&2; GPU_MODE=drm break;; @@ -158,15 +102,7 @@ if [ "$WAYLAND" -eq 1 ]; then "--bind" "$XDG_RUNTIME_DIR/$WAYLAND_DISPLAY" "$XDG_RUNTIME_DIR/$WAYLAND_DISPLAY" "--setenv" "WAYLAND_DISPLAY" "$WAYLAND_DISPLAY" ) - if [ "$ENV_DEFAULTS" -eq 1 ]; then - MUVM_ARGS+=( - "-e" "XDG_SESSION_TYPE=wayland" - "-e" "SDL_VIDEODRIVER=wayland" - "-e" "QT_QPA_PLATFORM=wayland" - "-e" "_JAVA_AWT_WM_NONREPARENTING=1" # e.g. with xwayland-satellite - "-e" "ELECTRON_OZONE_PLATFORM_HINT=wayland" # 28 < Electron < 39; newer should work by default - ) - fi + MUVM_ARGS+=("-e" "WAYLAND_DISPLAY=wayland-1") # the proxy is managed by us, not muvm fi if [ "$PIPEWIRE" -eq 1 ]; then @@ -184,11 +120,6 @@ if [ "$PIPEWIRE" -eq 1 ]; then PIPEWIRE_REMOTE=pipewire-0 fi BWRAP_ARGS+=("--bind" "$PIPEWIRE_RUNTIME_DIR/$PIPEWIRE_REMOTE" "$PIPEWIRE_RUNTIME_DIR/$PIPEWIRE_REMOTE") - if [ "$ENV_DEFAULTS" -eq 1 ]; then - MUVM_ARGS+=( - "-e" "SDL_AUDIO_DRIVER=pipewire" - ) - fi fi if [ "$X11" -eq 1 ]; then @@ -200,87 +131,43 @@ else unset DISPLAY XAUTHORITY fi -declare -a BG_PIDS - -cleanup() { - for pid in "${BG_PIDS[@]}"; do - if kill -0 "$pid" 2>/dev/null; then - echo "Killing process $pid" - kill -INT "$pid" - wait "$pid" 2>/dev/null - fi - done - exit -} - -trap cleanup EXIT INT TERM - -HOST_RUNTIME_DIR="$XDG_RUNTIME_DIR/munix.$$" -mkdir -p $HOST_RUNTIME_DIR -rm $HOST_RUNTIME_DIR/* -mkdir -p "$HOST_RUNTIME_DIR/home" -RUST_LOG=debug sidebus-broker \ - --path-mapping "/home=$HOST_RUNTIME_DIR/home" \ - "${SIDEBUS_ARGS[@]}" \ - --guest-mountpoint /mnt/munix-doc-portal/doc \ - --runtime-dir "$HOST_RUNTIME_DIR" \ - --unix-path "$HOST_RUNTIME_DIR/port.sock" & # >/dev/null 2>&1 & -BG_PIDS+=("$!") -while [ ! -S "$HOST_RUNTIME_DIR/port.sock" ]; do sleep 0.1; done -BWRAP_ARGS=( # prepend home mount before other mounts to not override custom bind mounts under /home - --bind "$HOST_RUNTIME_DIR/home" /home - "${BWRAP_ARGS[@]}" - --bind "$HOST_RUNTIME_DIR" /mnt/munix-doc-portal - --setenv "RUTABAGA_DBUS_CLIENT_SOCKET" /mnt/munix-doc-portal/port.sock -) -if [ "$ENV_DEFAULTS" -eq 1 ]; then - MUVM_ARGS+=( - "-e" "GTK_USE_PORTAL=1" # GTK 3 including Firefox - "-e" "QT_QPA_PLATFORMTHEME=xdgdesktopportal" - ) -fi - -if [ "$USING_PUBLISH" -eq 1 ]; then - printf "\n\n\n\e[1mNote: due to a \e[31mBUG\e[39m with port publishing (-p) you have to send the first outgoing packet (e.g. ping -c1 8.8.8.8) before your ports start receiving traffic. Sorry for the inconvenience!\e[39;0m\n\n\n\n" >&2 -fi - -# xxx: some time is lost to the starting process.. -[[ "$( +Date: Wed, 10 Sep 2025 15:44:41 -0300 +Subject: [PATCH] radv: detect platform:virtio-mmio devices for virtgpu native + context + +VirtIO devices can be configured as platform devices instead of PCI, +which is especially common in microVM projects like libkrun. + +Let's allow RADV to probe MMIO virtgpu devices. + +Signed-off-by: Val Packett +--- + src/amd/vulkan/radv_physical_device.c | 7 ++++--- + 1 file changed, 4 insertions(+), 3 deletions(-) + +diff --git a/src/amd/vulkan/radv_physical_device.c b/src/amd/vulkan/radv_physical_device.c +index 07b5b000b3ae..cd6f4c3488a1 100644 +--- a/src/amd/vulkan/radv_physical_device.c ++++ b/src/amd/vulkan/radv_physical_device.c +@@ -2507,14 +2507,15 @@ create_drm_physical_device(struct vk_instance *vk_instance, struct _drmDevice *d + #ifndef _WIN32 + bool supported_device = false; + +- if (!(device->available_nodes & (1 << DRM_NODE_RENDER)) || device->bustype != DRM_BUS_PCI) ++ if (!(device->available_nodes & (1 << DRM_NODE_RENDER))) + return VK_ERROR_INCOMPATIBLE_DRIVER; + + #ifdef HAVE_AMDGPU_VIRTIO +- supported_device |= device->deviceinfo.pci->vendor_id == VIRTGPU_PCI_VENDOR_ID; ++ supported_device |= device->bustype == DRM_BUS_PCI && device->deviceinfo.pci->vendor_id == VIRTGPU_PCI_VENDOR_ID; ++ supported_device |= device->bustype == DRM_BUS_PLATFORM; /* virtio-mmio */ + #endif + +- supported_device |= device->deviceinfo.pci->vendor_id == ATI_VENDOR_ID; ++ supported_device |= device->bustype == DRM_BUS_PCI && device->deviceinfo.pci->vendor_id == ATI_VENDOR_ID; + + if (!supported_device) + return VK_ERROR_INCOMPATIBLE_DRIVER; +-- +2.50.1 + diff --git a/systemd/microvm.target.wants/muvm-configure-network.service b/systemd/microvm.target.wants/muvm-configure-network.service deleted file mode 100644 index ca93c89..0000000 --- a/systemd/microvm.target.wants/muvm-configure-network.service +++ /dev/null @@ -1 +0,0 @@ -../muvm-configure-network.service \ No newline at end of file diff --git a/systemd/microvm.target.wants/muvm-remote.service b/systemd/microvm.target.wants/muvm-remote.service deleted file mode 100644 index 4f9f550..0000000 --- a/systemd/microvm.target.wants/muvm-remote.service +++ /dev/null @@ -1 +0,0 @@ -../muvm-remote.service \ No newline at end of file diff --git a/systemd/microvm.target.wants/pipewire-bridge.socket b/systemd/microvm.target.wants/pipewire-bridge.socket deleted file mode 100644 index 95e1850..0000000 --- a/systemd/microvm.target.wants/pipewire-bridge.socket +++ /dev/null @@ -1 +0,0 @@ -../pipewire-bridge.socket \ No newline at end of file diff --git a/systemd/microvm.target.wants/session-bus-bridge.service b/systemd/microvm.target.wants/session-bus-bridge.service deleted file mode 100644 index faa559d..0000000 --- a/systemd/microvm.target.wants/session-bus-bridge.service +++ /dev/null @@ -1 +0,0 @@ -../session-bus-bridge.service \ No newline at end of file diff --git a/systemd/microvm.target.wants/wayland-bridge.socket b/systemd/microvm.target.wants/wayland-bridge.socket deleted file mode 100644 index 4bcb084..0000000 --- a/systemd/microvm.target.wants/wayland-bridge.socket +++ /dev/null @@ -1 +0,0 @@ -../wayland-bridge.socket \ No newline at end of file diff --git a/systemd/muvm-configure-network.service b/systemd/muvm-configure-network.service deleted file mode 100644 index 3a67ff4..0000000 --- a/systemd/muvm-configure-network.service +++ /dev/null @@ -1,6 +0,0 @@ -[Unit] -Description=microVM Network configuration - -[Service] -Type=oneshot -ExecStart=/opt/bin/muvm-configure-network diff --git a/systemd/muvm-remote.service b/systemd/muvm-remote.service deleted file mode 100644 index 6164434..0000000 --- a/systemd/muvm-remote.service +++ /dev/null @@ -1,33 +0,0 @@ -[Unit] -After=sockets.target -Description=microVM Application runner -OnFailure=exit.target -OnSuccess=exit.target -Wants=sockets.target - -[Service] -Type=exec -# Environment="LOCALE_ARCHIVE=/nix/store/1hilqf0v1nm2w8xj87pwpm0rgq6lvhlv-glibc-locales-2.42-47/lib/locale/locale-archive" -# Environment="TZDIR=/nix/store/80izpiglrlqv2zb7rd7m5274k2dr142l-tzdata-2025c/share/zoneinfo" -Environment=WAYLAND_DISPLAY=wayland-1 -Environment=DBUS_SESSION_BUS_ADDRESS=unix:path=/run/vm-user/dbus.sock -Environment=PATH=/run/current-system/sw/bin -PassEnvironment=MESA_LOADER_DRIVER_OVERRIDE -PassEnvironment=MUVM_REMOTE_CONFIG -PassEnvironment=TERM -PassEnvironment=XDG_SESSION_TYPE -PassEnvironment=SDL_VIDEODRIVER -PassEnvironment=QT_QPA_PLATFORM -PassEnvironment=_JAVA_AWT_WM_NONREPARENTING -PassEnvironment=ELECTRON_OZONE_PLATFORM_HINT -PassEnvironment=GTK_USE_PORTAL -PassEnvironment=QT_QPA_PLATFORMTHEME -ExecStartPre=+/run/current-system/sw/bin/chown appvm:appvm /run/vm-user -ExecStart=/opt/bin/muvm-remote -ExecStopPost=+/nix/store/ygzfhw5nxrn7qqfqmz2s9p6cikcjqqkh-python3-3.13.11/bin/python -c "import os,fcntl,struct;print(os.getenv('EXIT_STATUS', '1'));fcntl.ioctl(os.open('/', os.O_RDONLY), 0x7602, int(os.getenv('EXIT_STATUS', '1')))" -User=appvm -Group=appvm -StandardError=tty -StandardInput=tty -StandardOutput=tty -TTYPath=/dev/hvc0 diff --git a/systemd/pipewire-bridge.service b/systemd/pipewire-bridge.service deleted file mode 100644 index 25c53e2..0000000 --- a/systemd/pipewire-bridge.service +++ /dev/null @@ -1,12 +0,0 @@ -[Unit] -Description=PipeWire VM bridge -Requires=pipewire-bridge.socket - -[Service] -Type=exec -ExecStart=/opt/bin/muvm-pwbridge - -# Environment=RUST_LOG=debug -# StandardError=tty -# StandardOutput=tty -# TTYPath=/dev/hvc0 diff --git a/systemd/pipewire-bridge.socket b/systemd/pipewire-bridge.socket deleted file mode 100644 index 998e661..0000000 --- a/systemd/pipewire-bridge.socket +++ /dev/null @@ -1,8 +0,0 @@ -[Unit] -Description=PipeWire VM bridge socket -PartOf=pipewire-bridge.service - -[Socket] -SocketGroup=appvm -SocketUser=appvm -ListenStream=/run/vm-user/pipewire-0 diff --git a/systemd/session-bus-bridge.service b/systemd/session-bus-bridge.service deleted file mode 100644 index 9b12a85..0000000 --- a/systemd/session-bus-bridge.service +++ /dev/null @@ -1,11 +0,0 @@ -[Unit] -After=session-bus.service -Description=D-Bus VM integration bridge -Requires=session-bus.socket session-bus.service - -[Service] -Environment=DBUS_SESSION_BUS_ADDRESS=unix:path=/run/vm-user/dbus.sock -ExecStartPre=+/run/current-system/sw/bin/chmod 0666 /dev/dri/card0 /dev/dri/renderD128 -ExecStart=/opt/bin/muvm-dbusbridge -Group=appvm -User=appvm diff --git a/systemd/wayland-bridge.service b/systemd/wayland-bridge.service deleted file mode 100644 index c74ba4e..0000000 --- a/systemd/wayland-bridge.service +++ /dev/null @@ -1,13 +0,0 @@ -[Unit] -Description=Wayland VM bridge -Requires=wayland-bridge.socket - -[Service] -ExecStartPre=+/run/current-system/sw/bin/chmod 0666 /dev/dri/card0 /dev/dri/renderD128 -ExecStart=/opt/bin/wl-cross-domain-proxy --listen-fd --filter-global wp_presentation -User=appvm -Group=appvm - -StandardError=tty -StandardOutput=tty -TTYPath=/dev/hvc0 diff --git a/systemd/wayland-bridge.socket b/systemd/wayland-bridge.socket deleted file mode 100644 index 2706a2b..0000000 --- a/systemd/wayland-bridge.socket +++ /dev/null @@ -1,9 +0,0 @@ -[Unit] -Description=Wayland VM bridge socket -PartOf=wayland-bridge.service - -[Socket] -FileDescriptorName=wayland -SocketGroup=appvm -SocketUser=appvm -ListenStream=/run/vm-user/wayland-1 diff --git a/templates/musictest/flake.nix b/templates/musictest/flake.nix deleted file mode 100644 index 406049b..0000000 --- a/templates/musictest/flake.nix +++ /dev/null @@ -1,71 +0,0 @@ -{ - nixConfig = { - extra-substituters = [ "https://cache.clan.lol" ]; - extra-trusted-public-keys = [ - "cache.clan.lol-1:3KztgSAB5R1M+Dz7vzkBGzXdodizbgLXGXKXlcQLA28=" - ]; - }; - - inputs = { - munix.url = "git+https://git.clan.lol/clan/munix?shallow=1&ref=main"; - nixpkgs.follows = "munix/nixpkgs"; - }; - - outputs = - { - nixpkgs, - munix, - ... - }: - let - forAllSystems = nixpkgs.lib.genAttrs [ - "x86_64-linux" - "aarch64-linux" - ]; - musictest-vm = - system: - nixpkgs.lib.nixosSystem { - modules = [ - munix.nixosModules.default - ( - { pkgs, ... }: - { - system.stateVersion = "26.05"; - virtualisation.munix.defaultCommand = "euphonica"; - - nixpkgs.hostPlatform = system; - - programs.dconf.enable = true; - fonts.packages = with pkgs; [ adwaita-fonts ]; - environment.systemPackages = with pkgs; [ euphonica ]; - - # Local background service as a demo that doesn't require network creds :) - services.mpd = { - enable = true; - startWhenNeeded = true; - musicDirectory = "/etc/demo-music"; - user = "appvm"; - group = "appvm"; - settings.audio_output = [ - { - type = "pipewire"; - name = "Pipewire Output"; - } - ]; - }; - environment.etc."demo-music/0101GhostsI.ogg".source = pkgs.fetchurl { - # just a CC-BY-SA licensed example - url = "https://archive.org/download/NineInchNailsGhostsI-Iv24bit48khz/0101GhostsI.ogg"; - sha256 = "0iijm1c191aqkxybl4a4gvlpnf72hk4896lwvp0xixkhds88qzxi"; - }; - } - ) - ]; - }; - in - { - packages = forAllSystems (system: { - default = (musictest-vm system).config.system.build.munix; - }); - }; -}