1# QEMU-related utilities shared between various Nix expressions.
2{ lib, pkgs }:
3
4let
5 zeroPad =
6 n:
7 lib.optionalString (n < 16) "0"
8 + (if n > 255 then throw "Can't have more than 255 nets or nodes!" else lib.toHexString n);
9in
10
11rec {
12 qemuNicMac = net: machine: "52:54:00:12:${zeroPad net}:${zeroPad machine}";
13
14 qemuNICFlags = nic: net: machine: [
15 "-device virtio-net-pci,netdev=vlan${toString nic},mac=${qemuNicMac net machine}"
16 ''-netdev vde,id=vlan${toString nic},sock="$QEMU_VDE_SOCKET_${toString net}"''
17 ];
18
19 qemuSerialDevice =
20 if with pkgs.stdenv.hostPlatform; isx86 || isLoongArch64 || isMips64 || isRiscV then
21 "ttyS0"
22 else if (with pkgs.stdenv.hostPlatform; isAarch || isPower) then
23 "ttyAMA0"
24 else
25 throw "Unknown QEMU serial device for system '${pkgs.stdenv.hostPlatform.system}'";
26
27 qemuBinary =
28 qemuPkg:
29 let
30 hostStdenv = qemuPkg.stdenv;
31 hostSystem = hostStdenv.system;
32 guestSystem = pkgs.stdenv.hostPlatform.system;
33
34 linuxHostGuestMatrix = {
35 x86_64-linux = "${qemuPkg}/bin/qemu-system-x86_64 -machine accel=kvm:tcg -cpu max";
36 armv7l-linux = "${qemuPkg}/bin/qemu-system-arm -machine virt,accel=kvm:tcg -cpu max";
37 aarch64-linux = "${qemuPkg}/bin/qemu-system-aarch64 -machine virt,gic-version=max,accel=kvm:tcg -cpu max";
38 powerpc64le-linux = "${qemuPkg}/bin/qemu-system-ppc64 -machine powernv";
39 powerpc64-linux = "${qemuPkg}/bin/qemu-system-ppc64 -machine powernv";
40 riscv32-linux = "${qemuPkg}/bin/qemu-system-riscv32 -machine virt";
41 riscv64-linux = "${qemuPkg}/bin/qemu-system-riscv64 -machine virt";
42 x86_64-darwin = "${qemuPkg}/bin/qemu-system-x86_64 -machine accel=kvm:tcg -cpu max";
43 };
44 otherHostGuestMatrix = {
45 aarch64-darwin = {
46 aarch64-linux = "${qemuPkg}/bin/qemu-system-aarch64 -machine virt,gic-version=2,accel=hvf:tcg -cpu max";
47 inherit (otherHostGuestMatrix.x86_64-darwin) x86_64-linux;
48 };
49 x86_64-darwin = {
50 x86_64-linux = "${qemuPkg}/bin/qemu-system-x86_64 -machine type=q35,accel=hvf:tcg -cpu max";
51 };
52 };
53
54 throwUnsupportedHostSystem =
55 let
56 supportedSystems = [ "linux" ] ++ (lib.attrNames otherHostGuestMatrix);
57 in
58 throw "Unsupported host system ${hostSystem}, supported: ${lib.concatStringsSep ", " supportedSystems}";
59 throwUnsupportedGuestSystem =
60 guestMap:
61 throw "Unsupported guest system ${guestSystem} for host ${hostSystem}, supported: ${lib.concatStringsSep ", " (lib.attrNames guestMap)}";
62 in
63 if hostStdenv.hostPlatform.isLinux then
64 linuxHostGuestMatrix.${guestSystem} or "${qemuPkg}/bin/qemu-kvm"
65 else
66 let
67 guestMap = (otherHostGuestMatrix.${hostSystem} or throwUnsupportedHostSystem);
68 in
69 (guestMap.${guestSystem} or (throwUnsupportedGuestSystem guestMap));
70}