QEMU: Difference between revisions

Onny (talk | contribs)
Emulate different architectures
DHCP (talk | contribs)
m Setup: formatting fixes for consistency across wiki: 1) don't nest `systemPackages` in `environment` 2) use <syntaxhighlight lang=console> and '$' prefix for shell commands
 
(8 intermediate revisions by 4 users not shown)
Line 1: Line 1:
[https://www.qemu.org/ QEMU] is a generic and open source machine emulator and virtualizer.
[https://www.qemu.org/ QEMU] is a generic and open source machine emulator and virtualizer.
For running virtual machines as a services see [[Libvirt]].


== Setup ==
== Setup ==
To install the main QEMU program system-wide, add the following to your <code>configuration.nix</code>:<syntaxhighlight lang=nix>
environment.systemPackages = [
  pkgs.qemu
];
</syntaxhighlight>


<syntaxhighlight lang=nix>
{{Evaluate}}
  environment = {
    systemPackages = [ pkgs.qemu ];
  };
</syntaxhighlight>


=== Quick EMU ===
=== Quick EMU ===
Line 15: Line 18:
https://github.com/quickemu-project/quickemu
https://github.com/quickemu-project/quickemu


<syntaxhighlight lang=bash>
<syntaxhighlight lang=console>
quickget windows 11
$ quickget windows 11
quickemu --vm windows-11.conf
$ quickemu --vm windows-11.conf
</syntaxhighlight>
</syntaxhighlight>


== Configuration ==
== Configuration ==


=== Booting UEFI ===
=== UEFI firmware support ===
To boot UEFI systems using QEMU, the UEFI firmware replacing the BIOS implementation needs to be provided while starting QEMU.
To enable UEFI firmware support in Virt-Manager, Libvirt, Gnome-Boxes etc. add following snippet to your system configuration and apply it<syntaxhighlight lang="nix">
systemd.tmpfiles.rules = [ "L+ /var/lib/qemu/firmware - - - - ${pkgs.qemu}/share/qemu/firmware" ];
</syntaxhighlight>


The following installs a script, that always starts QEMU with OVMF firmware implementing UEFI support.
=== Run binaries of different architecture ===
 
Following configuration will enable the emulation of different architectures. For example to run aarch64 and riscv64 binaries on an native x86_64 host, add following part to your system configuration, apply it and reboot your system.<syntaxhighlight lang="nix">
<syntaxhighlight lang=nix>
boot.binfmt.emulatedSystems = [
environment = {
  "aarch64-linux"
  systemPackages = [
  "riscv64-linux"
    (pkgs.writeShellScriptBin "qemu-system-x86_64-uefi" ''
];
      qemu-system-x86_64 \
        -bios ${pkgs.OVMF.fd}/FV/OVMF.fd \
        "$@"
    '')
  ];
};
</syntaxhighlight>
</syntaxhighlight>
qcow-efi images generated from [https://github.com/nix-community/nixos-generators nixos-generators] require more RAM than the default 128MB.  Failing to provide enough RAM results in grub reporting "error: start_image() returned 0x800000000000009." or systemd-boot reporting "Failed to execute NixOS: Out of resources".


== Tips and tricks ==
== Tips and tricks ==
Line 56: Line 53:
   outputs = { self, nixpkgs }:
   outputs = { self, nixpkgs }:
   let
   let
     pkgs = import nixpkgs { system = "x86_64-linux"; };
     # Put your actual system of your machine here. In VM terms it is the "HOST"
     pkgsAarch64 = import nixpkgs { system = "aarch64-linux"; };
     buildPlatform = "x86_64-linux";


     iso = (pkgsAarch64.nixos {
     # Put the system you want to emulate here. In VM terms it is the "GUEST"
    hostPlatform = "aarch64-linux";
 
    pkgs = import nixpkgs { system = buildPlatform; };
 
    vmConfig = (pkgs.nixos {
       imports = [ "${nixpkgs}/nixos/modules/installer/cd-dvd/installation-cd-base.nix" ];
       imports = [ "${nixpkgs}/nixos/modules/installer/cd-dvd/installation-cd-base.nix" ];
     }).config.system.build.isoImage;
      nixpkgs = { inherit buildPlatform hostPlatform; };
     });
    vmIso = vmConfig.config.system.build.isoImage;
    vmPkgs = vmConfig.pkgs;


     vmScript = pkgs.writeScriptBin "run-nixos-vm" ''
     vmScript = pkgs.writeShellScriptBin "run-nixos-vm" ''
      #!${pkgs.runtimeShell}
       ${pkgs.qemu}/bin/qemu-system-aarch64 \
       ${pkgs.qemu}/bin/qemu-system-aarch64 \
         -machine virt,gic-version=max \
         -machine virt,gic-version=max \
Line 70: Line 74:
         -m 2G \
         -m 2G \
         -smp 4 \
         -smp 4 \
         -drive file=$(echo ${iso}/iso/*.iso),format=raw,readonly=on \
         -drive file=$(echo ${vmIso}/iso/*.iso),format=raw,readonly=on \
         -nographic \
         -nographic \
         -bios ${pkgsAarch64.OVMF.fd}/FV/QEMU_EFI.fd
         -bios ${vmPkgs.OVMF.fd}/FV/OVMF.fd
     '';
     '';


   in {
   in {
     defaultPackage.x86_64-linux = vmScript;
     packages.x86_64-linux.default = vmScript;
   };
   };
}
}


</syntaxhighlight>
</syntaxhighlight>
Alternatively a different iso file can be specified in the drive-parameter, for example for Ubuntu Server ARM64.
Make sure to adjust the 2 toplevel variables to set up the cross compilation correctly. If your target is not AARCH64, you have to use the correct qemu binay in the start script.
[[Category:Virtualization]]
[[Category:Virtualization]]