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:
parent
17fa52824c
commit
5d96685ce5
134
bin/yino-vm
134
bin/yino-vm
@ -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)..."
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user