forked from mirrors/nixpkgs
virtualization/qemu-vm: fix and improve virtio/scsi switching
This commit is contained in:
parent
9e87b56dd1
commit
f777d2b719
|
@ -32,15 +32,21 @@ let
|
||||||
# expressions and shell script stuff.
|
# expressions and shell script stuff.
|
||||||
mkDiskIfaceDriveFlag = idx: driveArgs: let
|
mkDiskIfaceDriveFlag = idx: driveArgs: let
|
||||||
inherit (cfg.qemu) diskInterface;
|
inherit (cfg.qemu) diskInterface;
|
||||||
|
isSCSI = diskInterface == "scsi";
|
||||||
# The drive identifier created by incrementing the index by one using the
|
# The drive identifier created by incrementing the index by one using the
|
||||||
# shell.
|
# shell.
|
||||||
drvId = "drive$((${idx} + 1))";
|
drvId = "drive$((${idx} + 1))";
|
||||||
|
dvcId = "${diskInterface}$((${idx} + 1))";
|
||||||
# NOTE: DO NOT shell escape, because this may contain shell variables.
|
# NOTE: DO NOT shell escape, because this may contain shell variables.
|
||||||
commonArgs = "index=${idx},id=${drvId},${driveArgs}";
|
commonDriveArgs = "media=disk,id=${drvId},${driveArgs}";
|
||||||
isSCSI = diskInterface == "scsi";
|
commonInterfaceArgs = "drive=${drvId},id=${dvcId},bootindex=${idx}";
|
||||||
devArgs = "${diskInterface}-hd,drive=${drvId}";
|
in lib.concatStrings [
|
||||||
args = "-drive ${commonArgs},if=none -device lsi53c895a -device ${devArgs}";
|
"-drive ${commonDriveArgs},if=none "
|
||||||
in if isSCSI then args else "-drive ${commonArgs},if=${diskInterface}";
|
''${if isSCSI then
|
||||||
|
"-device lsi53c895a -device ${diskInterface}-hd,${commonInterfaceArgs}"
|
||||||
|
else
|
||||||
|
"-device virtio-blk-pci,scsi=off,${commonInterfaceArgs}"} ''
|
||||||
|
];
|
||||||
|
|
||||||
# Shell script to start the VM.
|
# Shell script to start the VM.
|
||||||
startVM =
|
startVM =
|
||||||
|
@ -97,15 +103,15 @@ let
|
||||||
-virtfs local,path=/nix/store,security_model=none,mount_tag=store \
|
-virtfs local,path=/nix/store,security_model=none,mount_tag=store \
|
||||||
-virtfs local,path=$TMPDIR/xchg,security_model=none,mount_tag=xchg \
|
-virtfs local,path=$TMPDIR/xchg,security_model=none,mount_tag=xchg \
|
||||||
-virtfs local,path=''${SHARED_DIR:-$TMPDIR/xchg},security_model=none,mount_tag=shared \
|
-virtfs local,path=''${SHARED_DIR:-$TMPDIR/xchg},security_model=none,mount_tag=shared \
|
||||||
|
${mkDiskIfaceDriveFlag "1" "file=$NIX_DISK_IMAGE,media=disk,cache=writeback,werror=report"} \
|
||||||
${if cfg.useBootLoader then ''
|
${if cfg.useBootLoader then ''
|
||||||
${mkDiskIfaceDriveFlag "0" "file=$NIX_DISK_IMAGE,cache=writeback,werror=report"} \
|
-boot menu=on \
|
||||||
${mkDiskIfaceDriveFlag "1" "file=$TMPDIR/disk.img,media=disk"} \
|
${mkDiskIfaceDriveFlag "0" "file=$TMPDIR/disk.img,media=disk"} \
|
||||||
${if cfg.useEFIBoot then ''
|
${if cfg.useEFIBoot then ''
|
||||||
-pflash $TMPDIR/bios.bin \
|
-pflash $TMPDIR/bios.bin \
|
||||||
'' else ''
|
'' else ''
|
||||||
''}
|
\''}
|
||||||
'' else ''
|
'' else '' \
|
||||||
${mkDiskIfaceDriveFlag "0" "file=$NIX_DISK_IMAGE,cache=writeback,werror=report"} \
|
|
||||||
-kernel ${config.system.build.toplevel}/kernel \
|
-kernel ${config.system.build.toplevel}/kernel \
|
||||||
-initrd ${config.system.build.toplevel}/initrd \
|
-initrd ${config.system.build.toplevel}/initrd \
|
||||||
-append "$(cat ${config.system.build.toplevel}/kernel-params) init=${config.system.build.toplevel}/init regInfo=${regInfo}/registration ${consoles} $QEMU_KERNEL_PARAMS" \
|
-append "$(cat ${config.system.build.toplevel}/kernel-params) init=${config.system.build.toplevel}/init regInfo=${regInfo}/registration ${consoles} $QEMU_KERNEL_PARAMS" \
|
||||||
|
@ -141,8 +147,9 @@ let
|
||||||
'';
|
'';
|
||||||
buildInputs = [ pkgs.utillinux ];
|
buildInputs = [ pkgs.utillinux ];
|
||||||
QEMU_OPTS = if cfg.useEFIBoot
|
QEMU_OPTS = if cfg.useEFIBoot
|
||||||
then "-pflash $out/bios.bin -nographic -serial pty"
|
then "-pflash $out/bios.bin -nographic"
|
||||||
else "-nographic -serial pty";
|
else "-nographic";
|
||||||
|
diskInterface = cfg.qemu.diskInterface;
|
||||||
}
|
}
|
||||||
''
|
''
|
||||||
# Create a /boot EFI partition with 40M and arbitrary but fixed GUIDs for reproducibility
|
# Create a /boot EFI partition with 40M and arbitrary but fixed GUIDs for reproducibility
|
||||||
|
@ -155,10 +162,10 @@ let
|
||||||
--partition-guid=1:1C06F03B-704E-4657-B9CD-681A087A2FDC \
|
--partition-guid=1:1C06F03B-704E-4657-B9CD-681A087A2FDC \
|
||||||
--partition-guid=2:970C694F-AFD0-4B99-B750-CDB7A329AB6F \
|
--partition-guid=2:970C694F-AFD0-4B99-B750-CDB7A329AB6F \
|
||||||
--hybrid 2 \
|
--hybrid 2 \
|
||||||
--recompute-chs /dev/vda
|
--recompute-chs ${config.virtualisation.bootDevice}
|
||||||
${pkgs.dosfstools}/bin/mkfs.fat -F16 /dev/vda2
|
${pkgs.dosfstools}/bin/mkfs.fat -F16 ${config.virtualisation.bootDevice}2
|
||||||
export MTOOLS_SKIP_CHECK=1
|
export MTOOLS_SKIP_CHECK=1
|
||||||
${pkgs.mtools}/bin/mlabel -i /dev/vda2 ::boot
|
${pkgs.mtools}/bin/mlabel -i ${config.virtualisation.bootDevice}2 ::boot
|
||||||
|
|
||||||
# Mount /boot; load necessary modules first.
|
# Mount /boot; load necessary modules first.
|
||||||
${pkgs.kmod}/bin/insmod ${pkgs.linux}/lib/modules/*/kernel/fs/nls/nls_cp437.ko.xz || true
|
${pkgs.kmod}/bin/insmod ${pkgs.linux}/lib/modules/*/kernel/fs/nls/nls_cp437.ko.xz || true
|
||||||
|
@ -167,11 +174,11 @@ let
|
||||||
${pkgs.kmod}/bin/insmod ${pkgs.linux}/lib/modules/*/kernel/fs/fat/vfat.ko.xz || true
|
${pkgs.kmod}/bin/insmod ${pkgs.linux}/lib/modules/*/kernel/fs/fat/vfat.ko.xz || true
|
||||||
${pkgs.kmod}/bin/insmod ${pkgs.linux}/lib/modules/*/kernel/fs/efivarfs/efivarfs.ko.xz || true
|
${pkgs.kmod}/bin/insmod ${pkgs.linux}/lib/modules/*/kernel/fs/efivarfs/efivarfs.ko.xz || true
|
||||||
mkdir /boot
|
mkdir /boot
|
||||||
mount /dev/vda2 /boot
|
mount ${config.virtualisation.bootDevice}2 /boot
|
||||||
|
|
||||||
# This is needed for GRUB 0.97, which doesn't know about virtio devices.
|
# This is needed for GRUB 0.97, which doesn't know about virtio devices.
|
||||||
mkdir /boot/grub
|
mkdir /boot/grub
|
||||||
echo '(hd0) /dev/vda' > /boot/grub/device.map
|
echo '(hd0) ${config.virtualisation.bootDevice}' > /boot/grub/device.map
|
||||||
|
|
||||||
# Install GRUB and generate the GRUB boot menu.
|
# Install GRUB and generate the GRUB boot menu.
|
||||||
touch /etc/NIXOS
|
touch /etc/NIXOS
|
||||||
|
@ -464,7 +471,8 @@ in
|
||||||
|
|
||||||
boot.initrd.availableKernelModules =
|
boot.initrd.availableKernelModules =
|
||||||
optional cfg.writableStore "overlay"
|
optional cfg.writableStore "overlay"
|
||||||
++ optional (cfg.qemu.diskInterface == "scsi") "sym53c8xx";
|
++ optional (cfg.qemu.diskInterface == "scsi") "sym53c8xx"
|
||||||
|
++ optional (cfg.qemu.diskInterface == "scsi") "virtio_scsi";
|
||||||
|
|
||||||
virtualisation.bootDevice =
|
virtualisation.bootDevice =
|
||||||
mkDefault (if cfg.qemu.diskInterface == "scsi" then "/dev/sda" else "/dev/vda");
|
mkDefault (if cfg.qemu.diskInterface == "scsi" then "/dev/sda" else "/dev/vda");
|
||||||
|
|
|
@ -3,8 +3,9 @@
|
||||||
, img ? pkgs.stdenv.hostPlatform.platform.kernelTarget
|
, img ? pkgs.stdenv.hostPlatform.platform.kernelTarget
|
||||||
, storeDir ? builtins.storeDir
|
, storeDir ? builtins.storeDir
|
||||||
, rootModules ?
|
, rootModules ?
|
||||||
[ "virtio_pci" "virtio_mmio" "virtio_blk" "virtio_balloon" "virtio_rng" "ext4" "unix" "9p" "9pnet_virtio" "crc32c_generic" ]
|
[ "virtio_pci" "virtio_mmio" "virtio_blk" "virtio_balloon" "virtio_rng" "ext4" "unix" "9p" "9pnet_virtio" "crc32c_generic" "sym53c8xx" "virtio_scsi" "ahci "]
|
||||||
++ pkgs.lib.optional (pkgs.stdenv.isi686 || pkgs.stdenv.isx86_64) "rtc_cmos"
|
++ pkgs.lib.optional (pkgs.stdenv.isi686 || pkgs.stdenv.isx86_64) "rtc_cmos"
|
||||||
|
, config
|
||||||
}:
|
}:
|
||||||
|
|
||||||
with pkgs;
|
with pkgs;
|
||||||
|
@ -196,9 +197,17 @@ rec {
|
||||||
${qemuBinary qemu} \
|
${qemuBinary qemu} \
|
||||||
-nographic -no-reboot \
|
-nographic -no-reboot \
|
||||||
-device virtio-rng-pci \
|
-device virtio-rng-pci \
|
||||||
|
${if "$diskInterface" == "scsi" then '' \
|
||||||
|
\ # FIXME: /dev/sda is not created within the VM
|
||||||
|
-device lsi53c895a \
|
||||||
|
-device scsi-hd,drive=hd,id=scsi1,bootindex=1 \
|
||||||
|
''${diskImage:+-drive file=$diskImage,media=disk,if=none,id=hd,cache=unsafe,werror=report} \
|
||||||
|
'' else '' \
|
||||||
|
-drive file=$diskImage,media=disk,if=none,id=hd \
|
||||||
|
-device virtio-blk-pci,scsi=off,drive=hd,id=virtio0,bootindex=1 \
|
||||||
|
\''}
|
||||||
-virtfs local,path=${storeDir},security_model=none,mount_tag=store \
|
-virtfs local,path=${storeDir},security_model=none,mount_tag=store \
|
||||||
-virtfs local,path=$TMPDIR/xchg,security_model=none,mount_tag=xchg \
|
-virtfs local,path=$TMPDIR/xchg,security_model=none,mount_tag=xchg \
|
||||||
''${diskImage:+-drive file=$diskImage,if=virtio,cache=unsafe,werror=report} \
|
|
||||||
-kernel ${kernel}/${img} \
|
-kernel ${kernel}/${img} \
|
||||||
-initrd ${initrd}/initrd \
|
-initrd ${initrd}/initrd \
|
||||||
-append "console=${qemuSerialDevice} panic=1 command=${stage2Init} out=$out mountDisk=$mountDisk loglevel=4" \
|
-append "console=${qemuSerialDevice} panic=1 command=${stage2Init} out=$out mountDisk=$mountDisk loglevel=4" \
|
||||||
|
@ -298,12 +307,13 @@ rec {
|
||||||
`run-vm' will be left behind in the temporary build directory
|
`run-vm' will be left behind in the temporary build directory
|
||||||
that allows you to boot into the VM and debug it interactively. */
|
that allows you to boot into the VM and debug it interactively. */
|
||||||
|
|
||||||
runInLinuxVM = drv: lib.overrideDerivation drv ({ memSize ? 512, QEMU_OPTS ? "", args, builder, ... }: {
|
runInLinuxVM = drv: lib.overrideDerivation drv ({ memSize ? 512, QEMU_OPTS ? "", args, builder, ... } @ moreArgs : {
|
||||||
requiredSystemFeatures = [ "kvm" ];
|
requiredSystemFeatures = [ "kvm" ];
|
||||||
builder = "${bash}/bin/sh";
|
builder = "${bash}/bin/sh";
|
||||||
args = ["-e" (vmRunCommand qemuCommandLinux)];
|
args = ["-e" (vmRunCommand qemuCommandLinux)];
|
||||||
origArgs = args;
|
origArgs = args;
|
||||||
origBuilder = builder;
|
origBuilder = builder;
|
||||||
|
diskInterface = "${moreArgs.diskInterface}";
|
||||||
QEMU_OPTS = "${QEMU_OPTS} -m ${toString memSize}";
|
QEMU_OPTS = "${QEMU_OPTS} -m ${toString memSize}";
|
||||||
passAsFile = []; # HACK fix - see https://github.com/NixOS/nixpkgs/issues/16742
|
passAsFile = []; # HACK fix - see https://github.com/NixOS/nixpkgs/issues/16742
|
||||||
});
|
});
|
||||||
|
|
Loading…
Reference in a new issue