From 5d96685ce5e7ed491270cd9e4ef337a43dad2eb1 Mon Sep 17 00:00:00 2001 From: Michael Smith Date: Fri, 20 Feb 2026 17:06:03 +0100 Subject: [PATCH] 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 --- bin/yino-vm | 134 ++++++++++++++++++++++++++++++++++------------------ 1 file changed, 89 insertions(+), 45 deletions(-) diff --git a/bin/yino-vm b/bin/yino-vm index 374a456..43991f9 100755 --- a/bin/yino-vm +++ b/bin/yino-vm @@ -4,67 +4,109 @@ set -euo pipefail VM_DIR="$(cd "$(dirname "$0")/.." && pwd)/vm" DISK_IMAGE="$VM_DIR/yino-vm.qcow2" 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 --- find_ovmf_code() { - local paths=( - /opt/homebrew/share/qemu/edk2-x86_64-code.fd - /usr/local/share/qemu/edk2-x86_64-code.fd - ) + local paths=() + if [[ "$HOST_OS" == "Darwin" ]]; then + 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 [[ -f "$p" ]] && echo "$p" && return done - # Cellar fallbacks - local cellar_dirs=(/opt/homebrew/Cellar/qemu /usr/local/Cellar/qemu) - for d in "${cellar_dirs[@]}"; do - if [[ -d "$d" ]]; then - local found - found=$(find "$d" -name 'edk2-x86_64-code.fd' -print -quit 2>/dev/null) - [[ -n "$found" ]] && echo "$found" && return - fi - done + if [[ "$HOST_OS" == "Darwin" ]]; then + local cellar_dirs=(/opt/homebrew/Cellar/qemu /usr/local/Cellar/qemu) + for d in "${cellar_dirs[@]}"; do + if [[ -d "$d" ]]; then + local found + found=$(find "$d" -name 'edk2-x86_64-code.fd' -print -quit 2>/dev/null) + [[ -n "$found" ]] && echo "$found" && return + fi + done + fi return 1 } find_ovmf_vars_template() { - local paths=( - /opt/homebrew/share/qemu/edk2-i386-vars.fd - /usr/local/share/qemu/edk2-i386-vars.fd - ) + local paths=() + if [[ "$HOST_OS" == "Darwin" ]]; then + 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 [[ -f "$p" ]] && echo "$p" && return done - local cellar_dirs=(/opt/homebrew/Cellar/qemu /usr/local/Cellar/qemu) - for d in "${cellar_dirs[@]}"; do - if [[ -d "$d" ]]; then - local found - found=$(find "$d" -name 'edk2-i386-vars.fd' -print -quit 2>/dev/null) - [[ -n "$found" ]] && echo "$found" && return - fi - done + if [[ "$HOST_OS" == "Darwin" ]]; then + local cellar_dirs=(/opt/homebrew/Cellar/qemu /usr/local/Cellar/qemu) + for d in "${cellar_dirs[@]}"; do + if [[ -d "$d" ]]; then + local found + found=$(find "$d" -name 'edk2-i386-vars.fd' -print -quit 2>/dev/null) + [[ -n "$found" ]] && echo "$found" && return + fi + done + fi return 1 } # --- CPU/accelerator auto-detection --- detect_accel() { - local arch - arch=$(uname -m) - if [[ "$arch" == "arm64" ]]; then - echo "tcg" - else + if [[ "$HOST_OS" == "Linux" && "$HOST_ARCH" == "x86_64" ]]; then + if [[ -w /dev/kvm ]]; then + echo "kvm" + 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" + else + echo "tcg" fi } detect_cpu() { - local arch - arch=$(uname -m) - if [[ "$arch" == "arm64" ]]; then - echo "qemu64" - else + local accel="$1" + if [[ "$accel" == "kvm" || "$accel" == "hvf" ]]; then echo "host" + else + echo "qemu64" fi } @@ -73,7 +115,7 @@ detect_cpu() { cmd_create() { if ! command -v qemu-system-x86_64 &>/dev/null; then echo "Error: qemu-system-x86_64 not found." >&2 - echo "Install it with: brew install qemu" >&2 + install_hint exit 1 fi @@ -85,8 +127,8 @@ cmd_create() { local vars_template if ! vars_template=$(find_ovmf_vars_template); then - echo "Error: OVMF vars template (edk2-i386-vars.fd) not found." >&2 - echo "Install it with: brew install qemu" >&2 + echo "Error: OVMF vars template not found." >&2 + install_hint exit 1 fi @@ -104,7 +146,7 @@ cmd_create() { cmd_boot() { if ! command -v qemu-system-x86_64 &>/dev/null; then echo "Error: qemu-system-x86_64 not found." >&2 - echo "Install it with: brew install qemu" >&2 + install_hint exit 1 fi @@ -116,8 +158,8 @@ cmd_boot() { local ovmf_code if ! ovmf_code=$(find_ovmf_code); then - echo "Error: OVMF firmware (edk2-x86_64-code.fd) not found." >&2 - echo "Install it with: brew install qemu" >&2 + echo "Error: OVMF firmware not found." >&2 + install_hint exit 1 fi @@ -129,11 +171,11 @@ cmd_boot() { local accel cpu accel=$(detect_accel) - cpu=$(detect_cpu) + cpu=$(detect_cpu "$accel") if [[ "$accel" == "tcg" ]]; then - echo "Warning: Running x86_64 VM under TCG emulation (Apple Silicon host)." - echo "This works but is significantly slower than hardware virtualization." + echo "Warning: Running x86_64 VM under TCG emulation — significantly slower" + echo "than hardware virtualization (KVM on Linux, HVF on Intel Mac)." echo "" fi @@ -168,8 +210,10 @@ cmd_boot() { local display_args if [[ "$serial" == true ]]; then display_args=(-serial mon:stdio -nographic -display none) - else + elif [[ "$HOST_OS" == "Darwin" ]]; then display_args=(-display cocoa -vga virtio) + else + display_args=(-display gtk -vga virtio) fi echo "Booting VM (accel=$accel, cpu=$cpu)..."