#! /usr/bin/env bash # Test a virtual machine with KVM on Apple M1. Notes: # # - Need QEMU 7 or later. # - Login via VNC to :5901. # - Expect to find QEMU_EFI.fd and QEMU_VARS.fd next to disk.img. # - Installing with -cdrom does not work, have to use scsi-cd: # # -device virtio-scsi-pci,id=scsi0 \ # -drive if=none,id=cd,file=/tmp/debian-....iso \ # -device scsi-cd,drive=cd # # - Replaced -usb (EHCI) with -device qemu-xhci (XHCI). # - Added virtio-gpu-pci (otherwise no graphical output). # - Added usb-kbd (otherwise no keyboard). # - Note: position of netdev dictates enp0sN name, so keep first PCI device. # - Must run on either P or E cores (https://gitlab.com/qemu-project/qemu/-/issues/1002). # - On M1 0-3 are E, 4-7 are P (lscpu, lscpu -e). # - On M1 Max 0-1 are E, 2-9 are P. # # -n # Network adapter to use, for example, virtio-net-pci (default), e1000, # or vmxnet3. # # -t # Existing tap interface to use instead of creating a new one (as tap9). # usage="usage: $0 [-n ] [...]" owd="$(pwd)" trap "{ cd '$owd'; exit 1; }" ERR set -o errtrace # Trap in functions. function info () { echo "$*" 1>&2; } function error () { info "$*"; exit 1; } br=br0 mac="de:ad:be:ef:b8:da" arch="$(uname -m)" kvm=(taskset -c 4-7 "qemu-system-$arch" -enable-kvm) nic=virtio-net-pci etap= while [ "$#" -gt 0 ]; do case "$1" in -n) shift nic="$1" shift ;; -t) shift etap="$1" shift ;; *) break ;; esac done dir="${1%/}" shift if [ -z "$dir" ]; then error "missing machine directory" fi if [ -z "$etap" ]; then tap=tap9 sudo ip tuntap delete "$tap" mode tap || true sudo ip tuntap add "$tap" mode tap user "$(whoami)" sudo ip link set "$tap" up #sleep 0.5s sudo ip link set "$tap" master "$br" else tap="$etap" fi "${kvm[@]}" \ -machine virt \ \ -m 4G \ -cpu host -smp "4,sockets=1,cores=4,threads=1" \ \ -drive "if=pflash,format=raw,readonly=on,file=$dir/QEMU_EFI.fd" \ -drive "if=pflash,format=raw,file=$dir/QEMU_VARS.fd" \ \ -netdev "tap,id=net0,ifname=$tap,script=no" \ -device "$nic,netdev=net0,mac=$mac" \ \ -drive "if=none,id=disk0,file=$dir/disk.img,format=raw" \ -device "virtio-blk-pci,scsi=off,drive=disk0" \ \ -device qemu-xhci \ -device usb-kbd \ -device usb-tablet \ \ -device virtio-gpu-pci \ -display default,show-cursor=on \ \ -vnc :1 \ \ -chardev stdio,id=qmp \ -mon chardev=qmp,mode=control,pretty=on \ \ -boot c "$@" if [ -z "$etap" ]; then sudo ip tuntap delete "$tap" mode tap fi