Add Linux amd64 support to yino-vm (KVM acceleration)

Enable running the dev VM on amd64 Linux hosts with KVM for
near-native speed, instead of being limited to slow TCG emulation
on Apple Silicon. Detects host OS/arch to select the right accelerator
(KVM, HVF, or TCG), OVMF firmware paths, and display backend.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Michael Smith 2026-02-20 17:06:03 +01:00
parent 17fa52824c
commit 5d96685ce5

View File

@ -4,67 +4,109 @@ set -euo pipefail
VM_DIR="$(cd "$(dirname "$0")/.." && pwd)/vm" VM_DIR="$(cd "$(dirname "$0")/.." && pwd)/vm"
DISK_IMAGE="$VM_DIR/yino-vm.qcow2" DISK_IMAGE="$VM_DIR/yino-vm.qcow2"
UEFI_VARS="$VM_DIR/yino-vm-vars.fd" UEFI_VARS="$VM_DIR/yino-vm-vars.fd"
HOST_OS=$(uname -s) # Darwin or Linux
HOST_ARCH=$(uname -m) # arm64 or x86_64
# --- Platform-aware install hints ---
install_hint() {
if [[ "$HOST_OS" == "Darwin" ]]; then
echo "Install it with: brew install qemu" >&2
else
echo "Install it with: sudo apt install qemu-system-x86 ovmf" >&2
fi
}
# --- OVMF firmware discovery --- # --- OVMF firmware discovery ---
find_ovmf_code() { find_ovmf_code() {
local paths=( local paths=()
/opt/homebrew/share/qemu/edk2-x86_64-code.fd if [[ "$HOST_OS" == "Darwin" ]]; then
/usr/local/share/qemu/edk2-x86_64-code.fd paths=(
) /opt/homebrew/share/qemu/edk2-x86_64-code.fd
/usr/local/share/qemu/edk2-x86_64-code.fd
)
else
paths=(
/usr/share/OVMF/OVMF_CODE_4M.fd
/usr/share/OVMF/OVMF_CODE.fd
/usr/share/qemu/OVMF_CODE_4M.fd
/usr/share/qemu/OVMF_CODE.fd
/usr/share/edk2/x64/OVMF_CODE.fd
)
fi
for p in "${paths[@]}"; do for p in "${paths[@]}"; do
[[ -f "$p" ]] && echo "$p" && return [[ -f "$p" ]] && echo "$p" && return
done done
# Cellar fallbacks if [[ "$HOST_OS" == "Darwin" ]]; then
local cellar_dirs=(/opt/homebrew/Cellar/qemu /usr/local/Cellar/qemu) local cellar_dirs=(/opt/homebrew/Cellar/qemu /usr/local/Cellar/qemu)
for d in "${cellar_dirs[@]}"; do for d in "${cellar_dirs[@]}"; do
if [[ -d "$d" ]]; then if [[ -d "$d" ]]; then
local found local found
found=$(find "$d" -name 'edk2-x86_64-code.fd' -print -quit 2>/dev/null) found=$(find "$d" -name 'edk2-x86_64-code.fd' -print -quit 2>/dev/null)
[[ -n "$found" ]] && echo "$found" && return [[ -n "$found" ]] && echo "$found" && return
fi fi
done done
fi
return 1 return 1
} }
find_ovmf_vars_template() { find_ovmf_vars_template() {
local paths=( local paths=()
/opt/homebrew/share/qemu/edk2-i386-vars.fd if [[ "$HOST_OS" == "Darwin" ]]; then
/usr/local/share/qemu/edk2-i386-vars.fd paths=(
) /opt/homebrew/share/qemu/edk2-i386-vars.fd
/usr/local/share/qemu/edk2-i386-vars.fd
)
else
paths=(
/usr/share/OVMF/OVMF_VARS_4M.fd
/usr/share/OVMF/OVMF_VARS.fd
/usr/share/qemu/OVMF_VARS_4M.fd
/usr/share/qemu/OVMF_VARS.fd
/usr/share/edk2/x64/OVMF_VARS.fd
)
fi
for p in "${paths[@]}"; do for p in "${paths[@]}"; do
[[ -f "$p" ]] && echo "$p" && return [[ -f "$p" ]] && echo "$p" && return
done done
local cellar_dirs=(/opt/homebrew/Cellar/qemu /usr/local/Cellar/qemu) if [[ "$HOST_OS" == "Darwin" ]]; then
for d in "${cellar_dirs[@]}"; do local cellar_dirs=(/opt/homebrew/Cellar/qemu /usr/local/Cellar/qemu)
if [[ -d "$d" ]]; then for d in "${cellar_dirs[@]}"; do
local found if [[ -d "$d" ]]; then
found=$(find "$d" -name 'edk2-i386-vars.fd' -print -quit 2>/dev/null) local found
[[ -n "$found" ]] && echo "$found" && return found=$(find "$d" -name 'edk2-i386-vars.fd' -print -quit 2>/dev/null)
fi [[ -n "$found" ]] && echo "$found" && return
done fi
done
fi
return 1 return 1
} }
# --- CPU/accelerator auto-detection --- # --- CPU/accelerator auto-detection ---
detect_accel() { detect_accel() {
local arch if [[ "$HOST_OS" == "Linux" && "$HOST_ARCH" == "x86_64" ]]; then
arch=$(uname -m) if [[ -w /dev/kvm ]]; then
if [[ "$arch" == "arm64" ]]; then echo "kvm"
echo "tcg" else
else echo "Warning: /dev/kvm not accessible. Install KVM and check permissions." >&2
echo " sudo apt install qemu-kvm && sudo usermod -aG kvm \$USER" >&2
echo "tcg"
fi
elif [[ "$HOST_OS" == "Darwin" && "$HOST_ARCH" == "x86_64" ]]; then
echo "hvf" echo "hvf"
else
echo "tcg"
fi fi
} }
detect_cpu() { detect_cpu() {
local arch local accel="$1"
arch=$(uname -m) if [[ "$accel" == "kvm" || "$accel" == "hvf" ]]; then
if [[ "$arch" == "arm64" ]]; then
echo "qemu64"
else
echo "host" echo "host"
else
echo "qemu64"
fi fi
} }
@ -73,7 +115,7 @@ detect_cpu() {
cmd_create() { cmd_create() {
if ! command -v qemu-system-x86_64 &>/dev/null; then if ! command -v qemu-system-x86_64 &>/dev/null; then
echo "Error: qemu-system-x86_64 not found." >&2 echo "Error: qemu-system-x86_64 not found." >&2
echo "Install it with: brew install qemu" >&2 install_hint
exit 1 exit 1
fi fi
@ -85,8 +127,8 @@ cmd_create() {
local vars_template local vars_template
if ! vars_template=$(find_ovmf_vars_template); then if ! vars_template=$(find_ovmf_vars_template); then
echo "Error: OVMF vars template (edk2-i386-vars.fd) not found." >&2 echo "Error: OVMF vars template not found." >&2
echo "Install it with: brew install qemu" >&2 install_hint
exit 1 exit 1
fi fi
@ -104,7 +146,7 @@ cmd_create() {
cmd_boot() { cmd_boot() {
if ! command -v qemu-system-x86_64 &>/dev/null; then if ! command -v qemu-system-x86_64 &>/dev/null; then
echo "Error: qemu-system-x86_64 not found." >&2 echo "Error: qemu-system-x86_64 not found." >&2
echo "Install it with: brew install qemu" >&2 install_hint
exit 1 exit 1
fi fi
@ -116,8 +158,8 @@ cmd_boot() {
local ovmf_code local ovmf_code
if ! ovmf_code=$(find_ovmf_code); then if ! ovmf_code=$(find_ovmf_code); then
echo "Error: OVMF firmware (edk2-x86_64-code.fd) not found." >&2 echo "Error: OVMF firmware not found." >&2
echo "Install it with: brew install qemu" >&2 install_hint
exit 1 exit 1
fi fi
@ -129,11 +171,11 @@ cmd_boot() {
local accel cpu local accel cpu
accel=$(detect_accel) accel=$(detect_accel)
cpu=$(detect_cpu) cpu=$(detect_cpu "$accel")
if [[ "$accel" == "tcg" ]]; then if [[ "$accel" == "tcg" ]]; then
echo "Warning: Running x86_64 VM under TCG emulation (Apple Silicon host)." echo "Warning: Running x86_64 VM under TCG emulation — significantly slower"
echo "This works but is significantly slower than hardware virtualization." echo "than hardware virtualization (KVM on Linux, HVF on Intel Mac)."
echo "" echo ""
fi fi
@ -168,8 +210,10 @@ cmd_boot() {
local display_args local display_args
if [[ "$serial" == true ]]; then if [[ "$serial" == true ]]; then
display_args=(-serial mon:stdio -nographic -display none) display_args=(-serial mon:stdio -nographic -display none)
else elif [[ "$HOST_OS" == "Darwin" ]]; then
display_args=(-display cocoa -vga virtio) display_args=(-display cocoa -vga virtio)
else
display_args=(-display gtk -vga virtio)
fi fi
echo "Booting VM (accel=$accel, cpu=$cpu)..." echo "Booting VM (accel=$accel, cpu=$cpu)..."