treewide: migrate to qemu-kvm in toolchain-bundle

Change-Id: I42a10a9adf7bdccb83ef997c6d554140ffaade4b
Reviewed-on: https://review.monogon.dev/c/monogon/+/4052
Reviewed-by: Jan Schär <jan@monogon.tech>
Tested-by: Jenkins CI
diff --git a/cloud/agent/e2e/BUILD.bazel b/cloud/agent/e2e/BUILD.bazel
index 91f09ce..ce068f8 100644
--- a/cloud/agent/e2e/BUILD.bazel
+++ b/cloud/agent/e2e/BUILD.bazel
@@ -4,6 +4,7 @@
     name = "e2e_test",
     srcs = ["main_test.go"],
     data = [
+        "//build/toolchain/toolchain-bundle:qemu-kvm",
         "//cloud/agent/takeover:initramfs",
         "//metropolis/installer/test/testos:testos_image",
         "//third_party/edk2:OVMF_CODE.fd",
@@ -16,6 +17,7 @@
         "xOvmfCodePath": "$(rlocationpath //third_party/edk2:OVMF_CODE.fd )",
         "xKernelPath": "$(rlocationpath //third_party/linux )",
         "xInitramfsOrigPath": "$(rlocationpath //cloud/agent/takeover:initramfs )",
+        "xQEMUPath": "$(rlocationpath //build/toolchain/toolchain-bundle:qemu-kvm )",
     },
     deps = [
         "//cloud/agent/api",
diff --git a/cloud/agent/e2e/main_test.go b/cloud/agent/e2e/main_test.go
index dc3108e..53b719b 100644
--- a/cloud/agent/e2e/main_test.go
+++ b/cloud/agent/e2e/main_test.go
@@ -47,13 +47,14 @@
 	xOvmfCodePath      string
 	xKernelPath        string
 	xInitramfsOrigPath string
+	xQEMUPath          string
 )
 
 func init() {
 	var err error
 	for _, path := range []*string{
 		&xImagePath, &xOvmfVarsPath, &xOvmfCodePath,
-		&xKernelPath, &xInitramfsOrigPath,
+		&xKernelPath, &xInitramfsOrigPath, &xQEMUPath,
 	} {
 		*path, err = runfiles.Rlocation(*path)
 		if err != nil {
@@ -277,11 +278,12 @@
 		"-kernel", xKernelPath,
 		"-initrd", initramfsFile.Name(),
 		"-append", "console=ttyS0 quiet")
-	qemuCmdAgent := exec.Command("qemu-system-x86_64", stage1Args...)
+	qemuCmdAgent := exec.Command(xQEMUPath, stage1Args...)
 	qemuCmdAgent.Stdout = os.Stdout
 	qemuCmdAgent.Stderr = os.Stderr
 	qemuCmdAgent.Run()
-	qemuCmdLaunch := exec.Command("qemu-system-x86_64", qemuArgs...)
+
+	qemuCmdLaunch := exec.Command(xQEMUPath, qemuArgs...)
 	stdoutPipe, err := qemuCmdLaunch.StdoutPipe()
 	if err != nil {
 		t.Fatal(err)
diff --git a/cloud/agent/takeover/e2e/BUILD.bazel b/cloud/agent/takeover/e2e/BUILD.bazel
index b83b131..2016a9d 100644
--- a/cloud/agent/takeover/e2e/BUILD.bazel
+++ b/cloud/agent/takeover/e2e/BUILD.bazel
@@ -9,12 +9,14 @@
         "//third_party/edk2:OVMF_CODE.fd",
         "//third_party/edk2:OVMF_VARS.fd",
         "@debian_11_cloudimage//file",
+        "//build/toolchain/toolchain-bundle:qemu-kvm",
     ],
     x_defs = {
         "xCloudImagePath": "$(rlocationpath @debian_11_cloudimage//file )",
         "xOvmfVarsPath": "$(rlocationpath //third_party/edk2:OVMF_VARS.fd )",
         "xOvmfCodePath": "$(rlocationpath //third_party/edk2:OVMF_CODE.fd )",
         "xTakeoverPath": "$(rlocationpath //cloud/agent/takeover )",
+        "xQEMUPath": "$(rlocationpath //build/toolchain/toolchain-bundle:qemu-kvm )",
     },
     deps = [
         "//cloud/agent/api",
diff --git a/cloud/agent/takeover/e2e/main_test.go b/cloud/agent/takeover/e2e/main_test.go
index 5387f92..e243d58 100644
--- a/cloud/agent/takeover/e2e/main_test.go
+++ b/cloud/agent/takeover/e2e/main_test.go
@@ -38,13 +38,14 @@
 	xOvmfVarsPath   string
 	xOvmfCodePath   string
 	xTakeoverPath   string
+	xQEMUPath       string
 )
 
 func init() {
 	var err error
 	for _, path := range []*string{
 		&xCloudImagePath, &xOvmfVarsPath, &xOvmfCodePath,
-		&xTakeoverPath,
+		&xTakeoverPath, &xQEMUPath,
 	} {
 		*path, err = runfiles.Rlocation(*path)
 		if err != nil {
@@ -111,7 +112,7 @@
 		"-serial", "stdio",
 		"-no-reboot",
 	}
-	qemuCmd := exec.Command("qemu-system-x86_64", qemuArgs...)
+	qemuCmd := exec.Command(xQEMUPath, qemuArgs...)
 	stdoutPipe, err := qemuCmd.StdoutPipe()
 	if err != nil {
 		t.Fatal(err)
diff --git a/metropolis/cli/takeover/e2e/BUILD.bazel b/metropolis/cli/takeover/e2e/BUILD.bazel
index d951ad8..4098904 100644
--- a/metropolis/cli/takeover/e2e/BUILD.bazel
+++ b/metropolis/cli/takeover/e2e/BUILD.bazel
@@ -4,6 +4,7 @@
     name = "e2e_test",
     srcs = ["main_test.go"],
     data = [
+        "//build/toolchain/toolchain-bundle:qemu-kvm",
         "//metropolis/cli/metroctl:metroctl_lite",
         "//metropolis/cli/takeover",
         "//metropolis/installer/test/testos:testos_image",
@@ -18,6 +19,7 @@
         "xCloudImagePath": "$(rlocationpath @debian_11_cloudimage//file )",
         "xTakeoverPath": "$(rlocationpath //metropolis/cli/takeover )",
         "xMetroctlPath": "$(rlocationpath //metropolis/cli/metroctl:metroctl_lite )",
+        "xQEMUPath": "$(rlocationpath //build/toolchain/toolchain-bundle:qemu-kvm )",
     },
     deps = [
         "//osbase/fat32",
diff --git a/metropolis/cli/takeover/e2e/main_test.go b/metropolis/cli/takeover/e2e/main_test.go
index d357d8a..419842f 100644
--- a/metropolis/cli/takeover/e2e/main_test.go
+++ b/metropolis/cli/takeover/e2e/main_test.go
@@ -38,6 +38,7 @@
 	xCloudImagePath string
 	xTakeoverPath   string
 	xMetroctlPath   string
+	xQEMUPath       string
 )
 
 func init() {
@@ -45,6 +46,7 @@
 	for _, path := range []*string{
 		&xCloudImagePath, &xOvmfVarsPath, &xOvmfCodePath,
 		&xTakeoverPath, &xImagePath, &xMetroctlPath,
+		&xQEMUPath,
 	} {
 		*path, err = runfiles.Rlocation(*path)
 		if err != nil {
@@ -157,7 +159,7 @@
 		"-device", "virtio-rng-pci",
 		"-serial", "stdio",
 	}
-	qemuCmd := exec.Command("qemu-system-x86_64", qemuArgs...)
+	qemuCmd := exec.Command(xQEMUPath, qemuArgs...)
 	stdoutPipe, err := qemuCmd.StdoutPipe()
 	if err != nil {
 		t.Fatal(err)
diff --git a/metropolis/installer/test/BUILD.bazel b/metropolis/installer/test/BUILD.bazel
index a5e8973..8aab4b4 100644
--- a/metropolis/installer/test/BUILD.bazel
+++ b/metropolis/installer/test/BUILD.bazel
@@ -7,6 +7,7 @@
     srcs = ["run_test.go"],
     data = [
         ":kernel",
+        "//build/toolchain/toolchain-bundle:qemu-kvm",
         "//metropolis/installer/test/testos:testos_image",
         "//third_party/edk2:OVMF_CODE.fd",
         "//third_party/edk2:OVMF_VARS.fd",
@@ -18,6 +19,7 @@
         "xOvmfCodePath": "$(rlocationpath //third_party/edk2:OVMF_CODE.fd )",
         "xInstallerPath": "$(rlocationpath :kernel )",
         "xImagePath": "$(rlocationpath //metropolis/installer/test/testos:testos_image )",
+        "xQEMUPath": "$(rlocationpath //build/toolchain/toolchain-bundle:qemu-kvm )",
     },
     deps = [
         "//metropolis/cli/metroctl/core",
diff --git a/metropolis/installer/test/run_test.go b/metropolis/installer/test/run_test.go
index 9d9d136..3da188a 100644
--- a/metropolis/installer/test/run_test.go
+++ b/metropolis/installer/test/run_test.go
@@ -39,6 +39,7 @@
 	xOvmfVarsPath  string
 	xInstallerPath string
 	xImagePath     string
+	xQEMUPath      string
 )
 
 func init() {
@@ -46,6 +47,7 @@
 	for _, path := range []*string{
 		&xOvmfCodePath, &xOvmfVarsPath,
 		&xInstallerPath, &xImagePath,
+		&xQEMUPath,
 	} {
 		*path, err = runfiles.Rlocation(*path)
 		if err != nil {
@@ -82,7 +84,7 @@
 	}
 	qemuArgs := append(defaultArgs, args...)
 	pf := cmd.TerminateIfFound(expectedOutput, nil)
-	return cmd.RunCommand(ctx, "qemu-system-x86_64", qemuArgs, pf)
+	return cmd.RunCommand(ctx, xQEMUPath, qemuArgs, pf)
 }
 
 // runQemuWithInstaller runs the Metropolis Installer in a qemu, performing the
diff --git a/metropolis/node/core/update/e2e/BUILD.bazel b/metropolis/node/core/update/e2e/BUILD.bazel
index 32f0f52..cd4bef9 100644
--- a/metropolis/node/core/update/e2e/BUILD.bazel
+++ b/metropolis/node/core/update/e2e/BUILD.bazel
@@ -13,6 +13,7 @@
         # For the two update tests
         "//metropolis/node/core/update/e2e/testos:testos_image_y",
         "//metropolis/node/core/update/e2e/testos:testos_image_z",
+        "//build/toolchain/toolchain-bundle:qemu-kvm",
     ],
     x_defs = {
         "xImageXPath": "$(rlocationpath //metropolis/node/core/update/e2e/testos:testos_image_x )",
@@ -21,6 +22,7 @@
         "xOvmfVarsPath": "$(rlocationpath //third_party/edk2:OVMF_VARS.fd )",
         "xOvmfCodePath": "$(rlocationpath //third_party/edk2:OVMF_CODE.fd )",
         "xAbloaderPath": "$(rlocationpath //metropolis/node/abloader )",
+        "xQEMUPath": "$(rlocationpath //build/toolchain/toolchain-bundle:qemu-kvm )",
     },
     deps = [
         "//metropolis/installer/install",
diff --git a/metropolis/node/core/update/e2e/e2e_test.go b/metropolis/node/core/update/e2e/e2e_test.go
index ba41f70..890a06f 100644
--- a/metropolis/node/core/update/e2e/e2e_test.go
+++ b/metropolis/node/core/update/e2e/e2e_test.go
@@ -38,6 +38,7 @@
 	xOvmfVarsPath string
 	xOvmfCodePath string
 	xAbloaderPath string
+	xQEMUPath     string
 )
 
 func init() {
@@ -45,7 +46,7 @@
 	for _, path := range []*string{
 		&xImageXPath, &xImageYPath, &xImageZPath,
 		&xOvmfVarsPath, &xOvmfCodePath,
-		&xAbloaderPath,
+		&xAbloaderPath, &xQEMUPath,
 	} {
 		*path, err = runfiles.Rlocation(*path)
 		if err != nil {
@@ -102,7 +103,7 @@
 	t.Helper()
 	ctx, cancel := context.WithTimeout(context.Background(), 60*time.Second)
 	defer cancel()
-	qemuCmdLaunch := exec.CommandContext(ctx, "qemu-system-x86_64", qemuArgs...)
+	qemuCmdLaunch := exec.CommandContext(ctx, xQEMUPath, qemuArgs...)
 	testosStarted := make(chan string, 1)
 	stdoutHandler(t, qemuCmdLaunch, cancel, testosStarted)
 	stderrHandler(t, qemuCmdLaunch)
@@ -249,7 +250,7 @@
 
 	ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
 	defer cancel()
-	qemuCmdLaunch := exec.CommandContext(ctx, "qemu-system-x86_64", qemuArgs...)
+	qemuCmdLaunch := exec.CommandContext(ctx, xQEMUPath, qemuArgs...)
 	testosStarted := make(chan string, 1)
 	stdoutHandler(t, qemuCmdLaunch, cancel, testosStarted)
 	stderrHandler(t, qemuCmdLaunch)
diff --git a/metropolis/test/launch/BUILD.bazel b/metropolis/test/launch/BUILD.bazel
index 6c76d5b..c03da7d 100644
--- a/metropolis/test/launch/BUILD.bazel
+++ b/metropolis/test/launch/BUILD.bazel
@@ -12,6 +12,7 @@
         "swtpm.go",
     ],
     data = [
+        "//build/toolchain/toolchain-bundle:qemu-kvm",
         "//metropolis/cli/metroctl:metroctl_lite",
         "//metropolis/node:oci_image_uncompressed",
         "//metropolis/node/abloader",
@@ -40,6 +41,7 @@
         "xInitramfsPath": "$(rlocationpath //metropolis/test/nanoswitch:initramfs )",
         "xNodeImagePath": "$(rlocationpath //metropolis/node:oci_image_uncompressed )",
         "xAbloaderPath": "$(rlocationpath //metropolis/node/abloader )",
+        "xQEMUPath": "$(rlocationpath //build/toolchain/toolchain-bundle:qemu-kvm )",
     },
     deps = [
         "//go/logging",
diff --git a/metropolis/test/launch/cluster.go b/metropolis/test/launch/cluster.go
index 118b82d..d2bbb4b 100644
--- a/metropolis/test/launch/cluster.go
+++ b/metropolis/test/launch/cluster.go
@@ -422,7 +422,7 @@
 	}
 
 	// Start the main qemu binary
-	systemCmd := exec.CommandContext(options.Runtime.ctxT, "qemu-system-x86_64", qemuArgs...)
+	systemCmd := exec.CommandContext(options.Runtime.ctxT, xQEMUPath, qemuArgs...)
 	if options.ConnectToSocket != nil {
 		systemCmd.ExtraFiles = []*os.File{options.ConnectToSocket}
 	}
diff --git a/metropolis/test/launch/launch.go b/metropolis/test/launch/launch.go
index 3864eb2..c1453b5 100644
--- a/metropolis/test/launch/launch.go
+++ b/metropolis/test/launch/launch.go
@@ -23,6 +23,7 @@
 	xInitramfsPath    string
 	xNodeImagePath    string
 	xAbloaderPath     string
+	xQEMUPath         string
 )
 
 func init() {
@@ -32,6 +33,7 @@
 		&xSwtpmCertPath, &xCerttoolPath, &xMetroctlPath,
 		&xOvmfCodePath, &xOvmfVarsPath, &xKernelPath,
 		&xInitramfsPath, &xNodeImagePath, &xAbloaderPath,
+		&xQEMUPath,
 	} {
 		*path, err = runfiles.Rlocation(*path)
 		if err != nil {
diff --git a/osbase/bringup/test/BUILD.bazel b/osbase/bringup/test/BUILD.bazel
index 66803bb..f63b0d6 100644
--- a/osbase/bringup/test/BUILD.bazel
+++ b/osbase/bringup/test/BUILD.bazel
@@ -15,6 +15,7 @@
         ":kernel_error",
         ":kernel_panic",
         ":kernel_succeeded",
+        "//build/toolchain/toolchain-bundle:qemu-kvm",
         "//third_party/edk2:OVMF_CODE.fd",
         "//third_party/edk2:OVMF_VARS.fd",
     ],
@@ -26,6 +27,7 @@
         "xSucceedKernelPath": "$(rlocationpath :kernel_succeeded )",
         "xPanicKernelPath": "$(rlocationpath :kernel_panic )",
         "xErrorKernelPath": "$(rlocationpath :kernel_error )",
+        "xQEMUPath": "$(rlocationpath //build/toolchain/toolchain-bundle:qemu-kvm )",
     },
     deps = [
         "//osbase/cmd",
diff --git a/osbase/bringup/test/run_test.go b/osbase/bringup/test/run_test.go
index 085b875..5b9b4cb 100644
--- a/osbase/bringup/test/run_test.go
+++ b/osbase/bringup/test/run_test.go
@@ -22,12 +22,13 @@
 	xSucceedKernelPath string
 	xPanicKernelPath   string
 	xErrorKernelPath   string
+	xQEMUPath          string
 )
 
 func init() {
 	var err error
 	for _, path := range []*string{
-		&xOvmfCodePath, &xOvmfVarsPath,
+		&xOvmfCodePath, &xOvmfVarsPath, &xQEMUPath,
 		&xSucceedKernelPath, &xPanicKernelPath, &xErrorKernelPath,
 	} {
 		*path, err = runfiles.Rlocation(*path)
@@ -56,7 +57,7 @@
 	}
 	qemuArgs := append(defaultArgs, args...)
 	pf := cmd.TerminateIfFound(expectedOutput, nil)
-	return cmd.RunCommand(ctx, "qemu-system-x86_64", qemuArgs, pf)
+	return cmd.RunCommand(ctx, xQEMUPath, qemuArgs, pf)
 }
 
 func TestBringupSuccess(t *testing.T) {
diff --git a/osbase/test/ktest/ktest.bzl b/osbase/test/ktest/ktest.bzl
index 4a6942f..5fc93e8 100644
--- a/osbase/test/ktest/ktest.bzl
+++ b/osbase/test/ktest/ktest.bzl
@@ -46,11 +46,12 @@
         is_executable = True,
     )
 
+    runfiles = ctx.runfiles(files = [ctx.file._ktest, initramfs, ctx.file.kernel, ctx.file.tester])
+    runfiles = runfiles.merge(ctx.attr._ktest[DefaultInfo].default_runfiles)
+
     return [DefaultInfo(
         executable = script_file,
-        runfiles = ctx.runfiles(
-            files = [ctx.files._ktest[0], initramfs, ctx.file.kernel, ctx.file.tester],
-        ),
+        runfiles = runfiles,
     )]
 
 k_test = rule(
@@ -105,7 +106,7 @@
             default = Label("//osbase/test/ktest"),
             cfg = "target",
             executable = True,
-            allow_files = True,
+            allow_single_file = True,
         ),
         "_ktest_init": attr.label(
             default = Label("//osbase/test/ktest/init"),
diff --git a/osbase/test/qemu/BUILD.bazel b/osbase/test/qemu/BUILD.bazel
index f45804f..0145ddb 100644
--- a/osbase/test/qemu/BUILD.bazel
+++ b/osbase/test/qemu/BUILD.bazel
@@ -3,13 +3,20 @@
 go_library(
     name = "qemu",
     srcs = ["launch.go"],
+    data = [
+        "//build/toolchain/toolchain-bundle:qemu-kvm",
+    ],
     importpath = "source.monogon.dev/osbase/test/qemu",
     visibility = [
         "//metropolis:__subpackages__",
         "//osbase:__subpackages__",
     ],
+    x_defs = {
+        "xQEMUPath": "$(rlocationpath //build/toolchain/toolchain-bundle:qemu-kvm )",
+    },
     deps = [
         "//osbase/freeport",
+        "@io_bazel_rules_go//go/runfiles",
         "@org_golang_x_sys//unix",
     ],
 )
diff --git a/osbase/test/qemu/launch.go b/osbase/test/qemu/launch.go
index 1b063de..ba33961 100644
--- a/osbase/test/qemu/launch.go
+++ b/osbase/test/qemu/launch.go
@@ -13,10 +13,12 @@
 	"net"
 	"os"
 	"os/exec"
+	"path/filepath"
 	"strconv"
 	"strings"
 	"syscall"
 
+	"github.com/bazelbuild/rules_go/go/runfiles"
 	"golang.org/x/sys/unix"
 
 	"source.monogon.dev/osbase/freeport"
@@ -136,6 +138,25 @@
 	return fd1, fd2, nil
 }
 
+var (
+	// These are filled by bazel at linking time with the canonical path of
+	// their corresponding file. Inside the init function we resolve it
+	// with the rules_go runfiles package to the real path.
+	xQEMUPath string
+)
+
+func init() {
+	var err error
+	for _, path := range []*string{
+		&xQEMUPath,
+	} {
+		*path, err = runfiles.Rlocation(*path)
+		if err != nil {
+			panic(err)
+		}
+	}
+}
+
 // MicroVMOptions contains all options to start a MicroVM
 type MicroVMOptions struct {
 	// Name is a human-readable identifier to be used in debug output.
@@ -240,7 +261,7 @@
 		"-m", "1G",
 		// Needed because QEMU does not boot without specifying the qboot bios
 		// even tho the documentation clearly states that this is the default.
-		"-bios", "/usr/share/qemu/qboot.rom",
+		"-bios", filepath.Join(filepath.Dir(xQEMUPath), "../share/qemu/qboot.rom"),
 		"-M", "microvm,x-option-roms=off,pic=off,pit=off,rtc=off,isa-serial=off",
 		"-kernel", opts.KernelPath,
 		// We force using a triple-fault reboot strategy since otherwise the kernel first
@@ -283,7 +304,7 @@
 	}
 
 	var stdErrBuf bytes.Buffer
-	cmd := exec.CommandContext(ctx, "/usr/bin/qemu-system-x86_64", append(baseArgs, extraArgs...)...)
+	cmd := exec.CommandContext(ctx, xQEMUPath, append(baseArgs, extraArgs...)...)
 	cmd.Stdout = opts.SerialPort
 	cmd.Stderr = &stdErrBuf