diff --git a/tstest/natlab/vmtest/qemu.go b/tstest/natlab/vmtest/qemu.go index 177c8bca9..5518e1650 100644 --- a/tstest/natlab/vmtest/qemu.go +++ b/tstest/natlab/vmtest/qemu.go @@ -13,6 +13,7 @@ import ( "os/exec" "path/filepath" "regexp" + "runtime" "strconv" "strings" "testing" @@ -21,6 +22,21 @@ import ( "tailscale.com/tstest/natlab/vnet" ) +// qemuAccelArgs returns QEMU command-line flags for hardware-accelerated +// virtualisation when available, or nil to fall back to TCG (software +// emulation). On Linux, KVM is used when /dev/kvm is accessible. On other +// platforms (macOS, etc.) TCG is used, which allows the tests to run +// without a same-architecture hypervisor at the cost of speed. +func qemuAccelArgs() []string { + if runtime.GOOS == "linux" { + if f, err := os.OpenFile("/dev/kvm", os.O_RDWR, 0); err == nil { + f.Close() + return []string{"-enable-kvm", "-cpu", "host"} + } + } + return nil +} + // gokrazyPlatform boots gokrazy (Linux) VMs via QEMU. type gokrazyPlatform struct{} @@ -125,6 +141,7 @@ func (e *Env) startGokrazyQEMU(n *Node) error { ) } + args = append(args, qemuAccelArgs()...) return e.launchQEMU(n.name, logPath, args) } @@ -148,9 +165,8 @@ func (e *Env) startCloudQEMU(n *Node) error { qmpSock := filepath.Join(e.tempDir, n.name+"-qmp.sock") args := []string{ - "-machine", "q35,accel=kvm", + "-machine", "q35", "-m", fmt.Sprintf("%dM", n.os.MemoryMB), - "-cpu", "host", "-smp", "2", "-display", "none", "-drive", fmt.Sprintf("file=%s,if=virtio", disk), @@ -179,6 +195,8 @@ func (e *Env) startCloudQEMU(n *Node) error { "-device", "virtio-net-pci,netdev=debug0,romfile=", ) + args = append(args, qemuAccelArgs()...) + if err := e.launchQEMU(n.name, logPath, args); err != nil { return err } diff --git a/tstest/natlab/vmtest/vmtest.go b/tstest/natlab/vmtest/vmtest.go index 8dbf720f6..e2c653e73 100644 --- a/tstest/natlab/vmtest/vmtest.go +++ b/tstest/natlab/vmtest/vmtest.go @@ -7,7 +7,7 @@ // and multi-NIC configurations for scenarios like subnet routing. // // Prerequisites: -// - qemu-system-x86_64 and KVM access (typically the "kvm" group; no root required) +// - qemu-system-x86_64 (KVM is used automatically on Linux when /dev/kvm is accessible) // - A built gokrazy natlabapp image (auto-built on first run via "make natlab" in gokrazy/) // // Run tests with: @@ -52,7 +52,7 @@ import ( ) var ( - runVMTests = flag.Bool("run-vm-tests", false, "run tests that require VMs with KVM") + runVMTests = flag.Bool("run-vm-tests", false, "run tests that require QEMU VMs") verboseVMDebug = flag.Bool("verbose-vm-debug", false, "enable verbose debug logging for VM tests") testVersion = flag.String("test-version", "", `if non-empty, download tailscale & tailscaled at the given release version (e.g. "1.97.255", "unstable", or "stable") instead of building from the source tree`) )