Working version of QEMU configuration

This commit is contained in:
Artur Gurgul 2025-08-11 17:36:55 +02:00
parent 49cc960703
commit 78d7233ff3
3 changed files with 138 additions and 2 deletions

126
lib/vm/qemu.rb Normal file
View file

@ -0,0 +1,126 @@
require "fileutils"
require "ostruct"
module Qemu
def self.qemu_bin_for(arch)
{
x86_64: "qemu-system-x86_64",
x86_32: "qemu-system-i386",
arm64: "qemu-system-aarch64",
armv7: "qemu-system-arm",
armv6: "qemu-system-arm",
armv5: "qemu-system-arm",
riscv64: "qemu-system-riscv64",
ppc64le: "qemu-system-ppc64",
ppc64: "qemu-system-ppc64",
ppc32: "qemu-system-ppc",
s390x: "qemu-system-s390x",
mips64el: "qemu-system-mips64el",
mips64: "qemu-system-mips64",
mipsel: "qemu-system-mipsel",
mips: "qemu-system-mips",
loongarch64: "qemu-system-loongarch64",
sparc64: "qemu-system-sparc64",
alpha: "qemu-system-alpha",
hppa: "qemu-system-hppa",
ia64: "qemu-system-ia64",
}.fetch(arch) { raise "Unsupported arch: #{arch.inspect}" }
end
def self.accel_args
host = RbConfig::CONFIG["host_os"]
if host =~ /linux/i && File.exist?("/dev/kvm")
["-accel", "kvm"]
elsif host =~ /darwin/i
# hvf exists on Apple Silicon + Intel macOS; QEMU falls back if not available
["-accel", "hvf"]
elsif host =~ /freebsd/i
# if QEMU was built with it; otherwise it will ignore
["-accel", "bhyve"]
else
["-accel", "tcg"]
end
end
def self.machine_args_for(arch)
case arch
when :x86_64, :x86_32
[]
when :arm64
# -machine type=virt
# -cpu cortex-a72
["-machine", "virt", "-cpu", "max"]
when :armv7, :armv6, :armv5
["-machine", "virt", "-cpu", "cortex-a15"]
when :riscv64
["-machine", "virt"]
when :loongarch64
["-machine", "virt"]
else
[]
end
end
#def self.launch(arch, disk_path, cdrom = nil, detach = true)
def self.launch(arch, disk_path, **options)
defaults = {
arch: System::ARCH,
cdrom: nil,
detach: true,
ram: 2048,
cpus: 1
}
opts = defaults.merge(options)
puts opts
qemu = qemu_bin_for(arch)
args = []
if System::OS == :macos && arch == :arm64
# args += ["-bios", "/opt/homebrew/share/qemu/edk2-aarch64-code.fd"]
args += ["-drive", "if=pflash,format=raw,unit=0,readonly=on,file=/opt/homebrew/share/qemu/edk2-aarch64-code.fd"]
#args += ["-device", "virtio-gpu-device"]
args += ["-display", "cocoa"]
args += ["-device", "qemu-xhci,id=xhci"]
args += ["-device", "usb-kbd"]
args += ["-device", "usb-tablet"]
args += ["-device", "virtio-keyboard-device"]
args += ["-device", "virtio-mouse-device"]
args += ["-device", "virtio-gpu"]
# copy to /Users/artur/.cache/dat/vm/debian/arm64/debian/vars.fd
# /opt/homebrew/share/qemu/edk2-aarch64-vars.fd
# args += ["-drive", "if=pflash,format=raw,unit=1,file=/Users/artur/.cache/dat/vm/debian/arm64/debian/vars.fd"]
end
args += accel_args
args += machine_args_for(arch)
args += ["-m", opts[:ram].to_s, "-smp", opts[:cpus].to_s]
args += ["-name", "FirstVM", "-boot", "order=d"] # boot from CD first
args += ["-drive", "file=#{disk_path},if=virtio,cache=writeback,format=raw"]
if opts[:cdrom] != nil
args += ["-cdrom", opts[:cdrom]]
end
args += ["-device", "virtio-net,netdev=n0", "-netdev", "user,id=n0"] # user-mode NAT
# optional: uncomment to run headless with VNC on :5901
# args += ["-display", "none", "-vnc", "127.0.0.1:1"]
cmd = [qemu, *args]
puts "Launching: #{cmd.join(' ')}"
pid = Process.spawn(*cmd, pgroup: true, out: $stdout, err: $stderr)
if opts[:detach]
Process.detach(pid)
puts "QEMU pid=#{pid}"
else
Process.wait(pid)
status = $?
puts "Exit status: #{status.exitstatus}"
end
end
end