Arm QEMU Debian 12 VM on Linux
The goal is to get a 64-bit arm64/aarch64 Debian VM running in QEMU on a typical x86_64/amd64 Linux host machine.
$ qemu-system-aarch64 --version
QEMU emulator version 8.2.2
Copyright (c) 2003-2023 Fabrice Bellard and the QEMU Project developers
The author’s lack of knowledge about Arm, QEMU, and Debian on Arm probably make this process a bit more complex than it needs to be. This article is a guide, but most likely not the best guide.
Download Files
Download the latest arm64 vmlinux kernel and
initrd.gz initramfs from
Debian. These files exist specifically for bootstrapping the
installation. These are special kernel and initramfs files for
installing Debian.
curl -O http://ftp.us.debian.org/debian/dists/stable/main/installer-arm64/current/images/cdrom/initrd.gz
curl -O http://ftp.us.debian.org/debian/dists/stable/main/installer-arm64/current/images/cdrom/vmlinuz
Download the latest
Debian arm64 DVD ISO. Version debian-12.5.0-arm64-DVD-1.iso at time of
writing.
curl -O -L https://cdimage.debian.org/debian-cd/current/arm64/iso-dvd/debian-12.5.0-arm64-DVD-1.iso
That ISO file, in conjunction with the vmlinux and
initrd.gz files, are how we install Debian. The
kernel and initramfs files allow us to boot to an installation
environment. The DVD iso file is the installation media that the
installer uses as a repository.
Install Debian
Create a disk for the Arm QEMU emulator image.
qemu-img create -f qcow2 debian-arm.sda.qcow2 100G
Boot the VM to install Debian.
qemu-system-aarch64 \
-m 4G \
-machine type=virt \
-cpu max \
-m 8g \
-smp 4 \
-initrd "./initrd.gz" \
-kernel "./vmlinuz" \
-append "console=ttyAMA0" \
-drive file=./debian-12.5.0-arm64-DVD-1.iso,id=cdrom,if=none,media=cdrom \
-device virtio-scsi-device \
-device scsi-cd,drive=cdrom \
-drive file="./debian-arm.sda.qcow2",id=hd,if=none,media=disk \
-device virtio-scsi-device \
-device scsi-hd,drive=hd \
-netdev user,id=net0,hostfwd=tcp::5555-:22 \
-device virtio-net-device,netdev=net0 \
-nographic
Follow the installation wizard. This will be a minimal
installation. Set a password for the root user.
Install Debian to a single partition. Do not enable disk
encryption. Do not install a desktop environment. Install the
standard system utilities and
SSH server software when prompted.
Installation may take a while.
When installation completes it is crucial to not reboot when prompted.
┌───────────────────┤ [!!] Finish the installation ├────────────────────┐
│ │
│ Installation complete │
│ Installation is complete, so it is time to boot into your new system. │
│ Make sure to remove the installation media, so that you boot into the │
│ new system rather than restarting the installation. │
│ │
│ <Go Back> <Continue> │
│ │
└───────────────────────────────────────────────────────────────────────┘
Choose Go Back at the
Finish the installation menu.
Choose to Execute a shell from the main installer
menu.
Delete the cdrom repository from apt.
chroot /target sh -c "sed -i '/deb cdrom/d' /etc/apt/sources.list"
Enable root SSH login for the installation.
chroot /target sh -c "echo 'PermitRootLogin yes' > /etc/ssh/sshd_config.d/root_ssh.conf"
Start sshd on the Debian installation so that we can
copy out the kernel and initramfs files from the guest to the
host.
chroot /target sh -c "mkdir -p /var/run/sshd && /sbin/sshd -D"
Use scp on the host machine to copy boot files from
the guest.
scp -P 5555 root@localhost:/boot/vmlinuz ./vmlinuz-from-guest
scp -P 5555 root@localhost:/boot/initrd.img ./initrd.img-from-guest
Use ctrl + c or another mechanism to stop
sshd.
Delete the SSH root login config file as it is
typically unsafe to allow root to log in using SSH.
chroot /target sh -c "rm /etc/ssh/sshd_config.d/root_ssh.conf"
Shut down the guest VM.
poweroff
Run VM Normally
Modify a few of the options for subsequent “normal” booting into the VM after installing Debian.
-
-appendmust haveroot=/dev/sda2(or another valid/devlocation) added in order to boot from the virtual hard drive. -
-drivefor thecdromis not needed at this point and can be removed -
-netdevis no longer needed and can be removed -
-initrdshould use the file copied out from the VM -
-kernelshould use the file copied out from the VM
qemu-system-aarch64 \
-m 4G \
-machine type=virt \
-cpu max \
-m 8g \
-smp 4 \
-initrd "./initrd.img-from-guest" \
-kernel "./vmlinuz-from-guest" \
-append "console=ttyAMA0 root=/dev/sda2" \
-drive file="./debian-arm.sda.qcow2",id=hd,if=none,media=disk \
-device virtio-scsi-device \
-device scsi-hd,drive=hd \
-netdev user,id=net0,hostfwd=tcp::5555-:22 \
-device virtio-net-device,netdev=net0 \
-nographic
The Debian VM should now be ready for use as a typical Debian machine.
If the vmlinux and initrd files are ever
updated in the VM they should be copied out and updated on the
host as was done during the initial setup.
Note: QEMU Arm Hardware is Picky
Please note that
Arm emulated boards/machine types are extremely specific about
the type of hardware they support. See the
QEMU docs on choosing a board model. For example, the virt machine type (-M / -machine) only supports PCI ethernet devices. Specifying a board that
supports 64-bit/aarch64 vs
32-bit boards has implications on the
cpu and other options that will be allowed.
The orangepi-pc machine type requires exactly 1GB of
RAM. The Raspberry Pi related machine types have similar
restrictions. Boards that simulate physical hardware must accept
parameters that align with that device type.
See this text here regarding the
QEMU Arm Versatile Express boards.
Note that as this hardware does not have PCI, IDE or SCSI, the only available storage option is emulated SD card.
See some example errors here for
qemu-system-arm configuration options that were
incompatible with the selected machine type.
qemu-system-arm: This machine can only be used with 512MiB or 1GiB RAM
qemu-system-arm: This board can only be used with cortex-a7 CPU
qemu-system-arm: Unsupported NIC model: rtl8139
qemu-system-arm: Invalid SD card size: 100 GiB
SD card size has to be a power of 2, e.g. 128 GiB.