Quick notes to run Debian arm64 (AArch64) as a virtualized guest using QEMU with KVM acceleration.

KVM support in the host kernel

$ cat /etc/gentoo-release
Gentoo Base System release 2.6

$ uname -rmo
4.19.49-v8-4395da031338-bis+ aarch64 GNU/Linux

$ ls /dev/kvm
/dev/kvm

$ cat /boot/config | grep KVM
CONFIG_HAVE_KVM_IRQCHIP=y
CONFIG_HAVE_KVM_IRQFD=y
CONFIG_HAVE_KVM_IRQ_ROUTING=y
CONFIG_HAVE_KVM_EVENTFD=y
CONFIG_KVM_MMIO=y
CONFIG_HAVE_KVM_MSI=y
CONFIG_HAVE_KVM_CPU_RELAX_INTERCEPT=y
CONFIG_KVM_VFIO=y
CONFIG_HAVE_KVM_ARCH_TLB_FLUSH_ALL=y
CONFIG_KVM_GENERIC_DIRTYLOG_READ_PROTECT=y
CONFIG_HAVE_KVM_IRQ_BYPASS=y
CONFIG_HAVE_KVM_VCPU_RUN_PID_CHANGE=y
CONFIG_KVM=y
CONFIG_KVM_ARM_HOST=y
CONFIG_KVM_ARM_PMU=y
CONFIG_KVM_INDIRECT_VECTORS=y

Create ROM images

Create two emulated 64MB NOR flash devices, holding the platform firmware and its persistent environment.

$ LIN_SNAPSHOTS=http://snapshots.linaro.org && \
  TC_EDK2=/components/kernel/leg-virt-tianocore-edk2-upstream && \
  QEMU_AARCH64_EFI=latest/QEMU-AARCH64/RELEASE_GCC5 && \
  wget ${LIN_SNAPSHOTS}/${TC_EDK2}/${QEMU_AARCH64_EFI}/QEMU_EFI.img.gz

$ gunzip QEMU_EFI.img.gz

$ qemu-img create -f qcow2 varstore.img 64M

Create block devices

$ DEB_ARM64_ISO_CD=https://cdimage.debian.org/debian-cd/current/arm64/iso-cd && \
  wget ${DEB_ARM64_ISO_CD}/debian-9.9.0-arm64-netinst.iso

$ qemu-img create -f qcow2 debian.img 8G

Run the installer

$ sudo qemu-system-aarch64 -m 256 -cpu host -M virt,accel=kvm -nographic \
   -drive if=pflash,format=raw,file=QEMU_EFI.img \
   -drive if=pflash,file=varstore.img \
   -drive if=virtio,file=debian.img \
   -netdev user,id=eth0,hostfwd=tcp:127.0.0.1:8022-:22 -device rtl8139,netdev=eth0 \
   -drive if=virtio,format=raw,file=debian-9.9.0-arm64-netinst.iso

The installer will not find the installation medium automatically because we do not ask qemu to read the ISO image. In case of asking, it will crash the system firmware we are using. Therefore at this point you see the following dialog box:

To locate the installation media:

Load CD-ROM drivers from removable media?: Select No

Manually select a CD-ROM module and device?: Select Yes

Module needed for accessing the CD-ROM: Select none

Device file for accessing the CD-ROM: Enter /dev/vdb and press Continue

You can finish the installation now.

Booting

You need to fix the boot process on your first run. Run the following command:

$ sudo qemu-system-aarch64 -m 256 -cpu host -M virt,accel=kvm -nographic \
   -drive if=pflash,format=raw,file=QEMU_EFI.img \
   -drive if=pflash,file=varstore.img \
   -drive if=virtio,file=debian.img \
   -netdev user,id=eth0,hostfwd=tcp:127.0.0.1:8022-:22 -device rtl8139,netdev=eth0

It will drop in an UEFI interactive shell:

Write the following commands to test the booting manually:

Shell> fs0:
Shell> \efi\debian\grubaa64.efi

Then you can write a startup.nsh file to automate the process:

  • Type fs0: at the UEFI Shell prompt
  • Type 'edit startup.nsh'
  • Type '\efi\debian\grubaa64.efi' and save it

Type Ctrl + E to show the editor's help:

The next time the system boots, it will detects the startup.nsh file and use it to boot the system. To stop it from loading the file, type Ctrl + C. This aborts the process, and returns you to the shell prompt.

If all things were ok you should see the serial login:

If you install an OpenSSH server in the guest, it will be also available through the 8022 host port bound in localhost.

The output of the dmesg command in a virtualized guest running on Raspberry Pi 3 B+ is available here.

Speeding the boot up

You can speed up the booting process loading the guest kernel and initrd.img images with the -kernel and -initrd options in the host.

$ sudo qemu-system-aarch64 -m 256 -cpu host -M virt,accel=kvm -nographic \
   -kernel vmlinuz -initrd initrd.img -append root=/dev/vda2 \
   -drive if=pflash,format=raw,file=QEMU_EFI.img \
   -drive if=pflash,file=varstore.img \
   -drive if=virtio,file=debian.img \
   -netdev user,id=eth0,hostfwd=tcp:127.0.0.1:8022-:22 -device rtl8139,netdev=eth0

References

Comments

comments powered by Disqus

Recent Entries