windows/pci: vIOMMU for nested passthrough, and a data disk built with the image
Three things, all in service of putting Proxmox in a VM that can still hand a
GPU to its own guests, and of a Windows VM whose profile survives its OS disk.
pci.viommu.enable emits `-device intel-iommu,intremap=on,caching-mode=on` and
forces kernel-irqchip=split, which interrupt remapping requires. Without an
IOMMU of its own a guest cannot bind a passed-through device to vfio-pci, so
it can never forward one on. The device leads the command line because QEMU
realizes devices in order and intel-iommu must precede what it translates.
pci.vgaPassthrough (default true, so nothing changes for existing VMs) makes
x-vga=on optional. It was forced on the first passthrough device, which is
wrong for a card the guest only forwards onward: it claims the VGA path the
emulated console adapter needs.
customizeImage gains extraDisk, a blank disk attached for the Audit Mode boot
and emitted as the derivation's `data` output. generalize uses it for dataDisk
and profilesDirectory, so the disk is partitioned and the profile relocated
under OOBE in the build VM. That is what removes the need for delayOobeRun --
previously the volume ProfilesDirectory names could not exist until the image
reached real hardware. A second output rather than a directory keeps ${image}
meaning the OS qcow2 for every existing consumer.
generalize also picks up staticIP and profilesDirectory.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0117qMyjpuXsjpVAcpJbFD8g
This commit is contained in:
parent
9784736260
commit
c213fc4db9
4 changed files with 122 additions and 4 deletions
|
|
@ -29,6 +29,12 @@
|
|||
compact ? false,
|
||||
# QEMU timeout in seconds (default 30 min, increase for Windows Update)
|
||||
qemuTimeout ? 1800,
|
||||
# Blank disk attached for the Audit Mode boot, e.g. { size = "100G"; }.
|
||||
# Windows sees it as disk 1, which is what lets a template partition it and
|
||||
# relocate profiles onto it in that same boot instead of deferring OOBE to
|
||||
# real hardware. Emitted as the derivation's `data` output, so whatever the
|
||||
# template writes to it survives the build.
|
||||
extraDisk ? null,
|
||||
}:
|
||||
let
|
||||
originalImageName = lib.strings.removeSuffix "-vmix" (lib.strings.removeSuffix ".qcow2" originalImage.name);
|
||||
|
|
@ -67,6 +73,11 @@
|
|||
]);
|
||||
|
||||
cdromArgs = lib.concatMapStringsSep " \\\n " (cd: "-drive file=${cd},media=cdrom,readonly=on") cdroms;
|
||||
extraDiskImg = "./extra.qcow2";
|
||||
extraDiskArgs = lib.optionalString (extraDisk != null)
|
||||
(if isAHCI
|
||||
then "-drive file=${extraDiskImg},format=qcow2,if=none,id=disk1 -device ide-hd,drive=disk1"
|
||||
else "-drive file=${extraDiskImg},format=qcow2,if=virtio");
|
||||
|
||||
displayArg = if vncDisplay != null then "-vnc ${vncDisplay}" else null;
|
||||
|
||||
|
|
@ -109,6 +120,7 @@
|
|||
then "-drive file=${resultImg},format=qcow2,if=none,id=disk0 -device ide-hd,drive=disk0"
|
||||
else "-drive file=${resultImg},format=qcow2,if=virtio"} \
|
||||
${cdromArgs} \
|
||||
${extraDiskArgs} \
|
||||
-nic user,model=${if nicModel != null then nicModel else if isAHCI then "e1000" else "virtio-net-pci"}"
|
||||
|
||||
timeout ${toString qemuTimeout} qemu-system-x86_64 $VMIX_DISPLAY $QEMU_ARGS || \
|
||||
|
|
@ -127,6 +139,10 @@
|
|||
# create resulting image backed by original image
|
||||
qemu-img create -f qcow2 -b ${originalImage} -F qcow2 ${resultImg}
|
||||
[ -n "${diskSize}" ] && qemu-img resize ${resultImg} ${diskSize}
|
||||
${lib.optionalString (extraDisk != null) ''
|
||||
echo "=== vmix: creating extra disk (${extraDisk.size}) ==="
|
||||
qemu-img create -f qcow2 ${extraDiskImg} ${extraDisk.size}
|
||||
''}
|
||||
${virtWinRegMerge}
|
||||
${auditBootCommands}
|
||||
${lib.optionalString compact ''
|
||||
|
|
@ -135,10 +151,14 @@
|
|||
mv compact.qcow2 ${resultImg}
|
||||
''}
|
||||
mv ${resultImg} $out
|
||||
${lib.optionalString (extraDisk != null) "mv ${extraDiskImg} $data"}
|
||||
'';
|
||||
builtImage = pkgs.runCommand customImageName ({
|
||||
nativeBuildInputs = with pkgs; [ qemu perl guestfs-tools ];
|
||||
requiredSystemFeatures = [ "kvm" ];
|
||||
} // lib.optionalAttrs impure { __noChroot = true; }) builderCommand;
|
||||
} // lib.optionalAttrs impure { __noChroot = true; }
|
||||
# A second output rather than a directory, so ${image} keeps meaning the OS
|
||||
# qcow2 for every existing consumer and the fold can still back onto it.
|
||||
// lib.optionalAttrs (extraDisk != null) { outputs = [ "out" "data" ]; }) builderCommand;
|
||||
in
|
||||
builtImage // { _vmixOsType = "windows"; useAHCI = isAHCI; }
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue