diff --git a/pkg/provision/providers/qemu/arch.go b/pkg/provision/providers/qemu/arch.go index eb428feeb3..d02ef5b418 100644 --- a/pkg/provision/providers/qemu/arch.go +++ b/pkg/provision/providers/qemu/arch.go @@ -5,8 +5,10 @@ package qemu import ( + "fmt" "os/exec" "path/filepath" + "slices" ) // Arch abstracts away differences between different architectures. @@ -74,18 +76,47 @@ type PFlash struct { func (arch Arch) PFlash(uefiEnabled bool, extraUEFISearchPaths []string) []PFlash { switch arch { case ArchArm64: - uefiSourcePaths := []string{"/usr/share/qemu-efi-aarch64/QEMU_EFI.fd", "/usr/share/OVMF/QEMU_EFI.fd", "/usr/share/edk2/aarch64/QEMU_EFI.fd"} - for _, p := range extraUEFISearchPaths { - uefiSourcePaths = append(uefiSourcePaths, filepath.Join(p, "QEMU_EFI.fd")) + // default search paths + uefiSourcePathPrefixes := []string{ + "/usr/share/AAVMF", // most standard location + "/usr/share/qemu-efi-aarch64", + "/usr/share/OVMF", + "/usr/share/edk2/aarch64", // Fedora + "/usr/share/edk2/experimental", // Fedora + } + + // Secure boot enabled firmware files + uefiSourceFiles := []string{ + "AAVMF_CODE.secboot.fd", // debian, EFI vars not protected + "QEMU_EFI.secboot.testonly.fd", // Fedora, ref: https://bugzilla.redhat.com/show_bug.cgi?id=1882135 + } + + // Non-secure boot firmware files + uefiSourceFilesInsecure := []string{ + "AAVMF_CODE.fd", + "QEMU_EFI.fd", + "OVMF.stateless.fd", + } + + // Empty vars files + uefiVarsFiles := []string{ + "AAVMF_VARS.fd", + "QEMU_VARS.fd", } + // Append extra search paths + uefiSourcePathPrefixes = append(uefiSourcePathPrefixes, extraUEFISearchPaths...) + + uefiSourcePaths, uefiVarsPaths := generateUEFIPFlashList(uefiSourcePathPrefixes, uefiSourceFiles, uefiVarsFiles, uefiSourceFilesInsecure) + return []PFlash{ { Size: 64 * 1024 * 1024, SourcePaths: uefiSourcePaths, }, { - Size: 64 * 1024 * 1024, + SourcePaths: uefiVarsPaths, + Size: 64 * 1024 * 1024, }, } case ArchAmd64: @@ -127,25 +158,7 @@ func (arch Arch) PFlash(uefiEnabled bool, extraUEFISearchPaths []string) []PFlas // Append extra search paths uefiSourcePathPrefixes = append(uefiSourcePathPrefixes, extraUEFISearchPaths...) - var uefiSourcePaths []string - - var uefiVarsPaths []string - - for _, p := range uefiSourcePathPrefixes { - for _, f := range uefiSourceFiles { - uefiSourcePaths = append(uefiSourcePaths, filepath.Join(p, f)) - } - - for _, f := range uefiVarsFiles { - uefiVarsPaths = append(uefiVarsPaths, filepath.Join(p, f)) - } - } - - for _, p := range uefiSourcePathPrefixes { - for _, f := range uefiSourceFilesInsecure { - uefiSourcePaths = append(uefiSourcePaths, filepath.Join(p, f)) - } - } + uefiSourcePaths, uefiVarsPaths := generateUEFIPFlashList(uefiSourcePathPrefixes, uefiSourceFiles, uefiVarsFiles, uefiSourceFilesInsecure) return []PFlash{ { @@ -162,6 +175,26 @@ func (arch Arch) PFlash(uefiEnabled bool, extraUEFISearchPaths []string) []PFlas } } +func generateUEFIPFlashList(uefiSourcePathPrefixes, uefiSourceFiles, uefiVarsFiles, uefiSourceFilesInsecure []string) (uefiSourcePaths, uefiVarsPaths []string) { + for _, p := range uefiSourcePathPrefixes { + for _, f := range uefiSourceFiles { + uefiSourcePaths = append(uefiSourcePaths, filepath.Join(p, f)) + } + + for _, f := range uefiVarsFiles { + uefiVarsPaths = append(uefiVarsPaths, filepath.Join(p, f)) + } + } + + for _, p := range uefiSourcePathPrefixes { + for _, f := range uefiSourceFilesInsecure { + uefiSourcePaths = append(uefiSourcePaths, filepath.Join(p, f)) + } + } + + return uefiSourcePaths, uefiVarsPaths +} + // QemuExecutable returns name of qemu executable for the arch. func (arch Arch) QemuExecutable() string { binaries := []string{ @@ -179,7 +212,43 @@ func (arch Arch) QemuExecutable() string { return "" } -// Architecture returns the architecture. -func (arch Arch) Architecture() string { - return string(arch) +// TPMDeviceArgs returns arguments for qemu to enable TPM device. +func (arch Arch) TPMDeviceArgs(socketPath string) []string { + tpmDeviceArgs := []string{ + "-chardev", + fmt.Sprintf("socket,id=chrtpm,path=%s", socketPath), + "-tpmdev", + "emulator,id=tpm0,chardev=chrtpm", + "-device", + } + + switch arch { + case ArchAmd64: + return slices.Concat(tpmDeviceArgs, []string{"tpm-tis,tpmdev=tpm0"}) + case ArchArm64: + return slices.Concat(tpmDeviceArgs, []string{"tpm-tis-device,tpmdev=tpm0"}) + default: + panic("unsupported architecture") + } +} + +// KVMArgs returns arguments for qemu to enable KVM. +func (arch Arch) KVMArgs(kvmEnabled bool) []string { + if !kvmEnabled { + return []string{"-machine", arch.QemuMachine()} + } + + machineArg := arch.QemuMachine() + ",accel=kvm" + + switch arch { + case ArchAmd64: + machineArg += ",smm=on" + + return []string{"-machine", machineArg} + case ArchArm64: + // smm is not supported on aarch64 + return []string{"-machine", machineArg} + default: + panic("unsupported architecture") + } } diff --git a/pkg/provision/providers/qemu/launch.go b/pkg/provision/providers/qemu/launch.go index 1a1ff44c67..5f94643b67 100644 --- a/pkg/provision/providers/qemu/launch.go +++ b/pkg/provision/providers/qemu/launch.go @@ -43,14 +43,11 @@ type LaunchConfig struct { DiskDrivers []string VCPUCount int64 MemSize int64 - QemuExecutable string - Architecture string KernelImagePath string InitrdPath string ISOPath string PFlashImages []string KernelArgs string - MachineType string MonitorPath string DefaultBootOrder string EnableKVM bool @@ -58,6 +55,7 @@ type LaunchConfig struct { TPM2Config tpm2Config NodeUUID uuid.UUID BadRTC bool + ArchitectureData Arch // Talos config Config string @@ -390,18 +388,7 @@ func launchVM(config *LaunchConfig) error { } } - machineArg := config.MachineType - - if config.EnableKVM { - machineArg += ",accel=kvm" - - // smm is not supported on aarch64 - if Arch(config.QemuExecutable) == ArchAmd64 { - machineArg += ",smm=on" - } - } - - args = append(args, "-machine", machineArg) + args = append(args, config.ArchitectureData.KVMArgs(config.EnableKVM)...) pflashArgs := make([]string, 2*len(config.PFlashImages)) for i := range config.PFlashImages { @@ -440,12 +427,7 @@ func launchVM(config *LaunchConfig) error { } args = append(args, - "-chardev", - fmt.Sprintf("socket,id=chrtpm,path=%s", tpm2SocketPath), - "-tpmdev", - "emulator,id=tpm0,chardev=chrtpm", - "-device", - "tpm-tis,tpmdev=tpm0", + config.ArchitectureData.TPMDeviceArgs(tpm2SocketPath)..., ) } @@ -470,9 +452,9 @@ func launchVM(config *LaunchConfig) error { ) } - fmt.Fprintf(os.Stderr, "starting %s with args:\n%s\n", config.QemuExecutable, strings.Join(args, " ")) + fmt.Fprintf(os.Stderr, "starting %s with args:\n%s\n", config.ArchitectureData.QemuExecutable(), strings.Join(args, " ")) cmd := exec.Command( - config.QemuExecutable, + config.ArchitectureData.QemuExecutable(), args..., ) diff --git a/pkg/provision/providers/qemu/node.go b/pkg/provision/providers/qemu/node.go index c7b0eaf826..e7f60e725e 100644 --- a/pkg/provision/providers/qemu/node.go +++ b/pkg/provision/providers/qemu/node.go @@ -129,16 +129,14 @@ func (p *provisioner) createNode(state *vm.State, clusterReq provision.ClusterRe } launchConfig := LaunchConfig{ - QemuExecutable: arch.QemuExecutable(), - Architecture: arch.Architecture(), - DiskPaths: diskPaths, + ArchitectureData: arch, + DiskPaths: diskPaths, DiskDrivers: xslices.Map(nodeReq.Disks, func(disk *provision.Disk) string { return disk.Driver }), VCPUCount: vcpuCount, MemSize: memSize, KernelArgs: cmdline.String(), - MachineType: arch.QemuMachine(), PFlashImages: pflashImages, MonitorPath: state.GetRelativePath(fmt.Sprintf("%s.monitor", nodeReq.Name)), EnableKVM: opts.TargetArch == runtime.GOARCH,