From 5d0e677397c85bf7897d51841e6a53033d06a607 Mon Sep 17 00:00:00 2001 From: Rolf Neugebauer Date: Thu, 1 Feb 2018 16:29:38 +0000 Subject: [PATCH] cmd/qemu: Enable additional accelerators Upstream qemu supports accelerators other than kvm. Allow the user to choose. On Linux we still default to 'lvm' if available. On macOS we try the new 'hvf' accelerator, if available. Disable acceleration if the host arch does not match requested qemu arch. Also change the LINUXKIT_QEMU_KVM env var to LINUXKIT_QEMU_ACCEL and use the functions in utils.go for env var overrides. Signed-off-by: Rolf Neugebauer --- src/cmd/linuxkit/run_qemu.go | 58 +++++++++++++++++++++--------------- 1 file changed, 34 insertions(+), 24 deletions(-) diff --git a/src/cmd/linuxkit/run_qemu.go b/src/cmd/linuxkit/run_qemu.go index 753eda2bf..7ba1933ab 100644 --- a/src/cmd/linuxkit/run_qemu.go +++ b/src/cmd/linuxkit/run_qemu.go @@ -38,7 +38,7 @@ type QemuConfig struct { Arch string CPUs string Memory string - KVM bool + Accel string Containerized bool QemuBinPath string QemuImgPath string @@ -56,7 +56,8 @@ const ( ) var ( - defaultArch string + defaultArch string + defaultAccel string ) func init() { @@ -66,6 +67,12 @@ func init() { case "amd64": defaultArch = "x86_64" } + switch { + case haveKVM(): + defaultAccel = "kvm:tcg" + case runtime.GOOS == "darwin": + defaultAccel = "hvf:tcg" + } } func haveKVM() bool { @@ -73,19 +80,6 @@ func haveKVM() bool { return !os.IsNotExist(err) } -func envOverrideBool(env string, b *bool) { - val := os.Getenv(env) - if val == "" { - return - } - - var err error - *b, err = strconv.ParseBool(val) - if err != nil { - log.Fatal("Unable to parse %q=%q as a boolean", env, val) - } -} - func retrieveMAC(statePath string) net.HardwareAddr { var mac net.HardwareAddr fileName := filepath.Join(statePath, "mac-addr") @@ -160,7 +154,7 @@ func runQemu(args []string) { fw := flags.String("fw", "", "Path to OVMF firmware for UEFI boot") // VM configuration - enableKVM := flags.Bool("kvm", haveKVM(), "Enable KVM acceleration") + accel := flags.String("accel", defaultAccel, "Choose acceleration mode. Use 'tcg' to disable it.") arch := flags.String("arch", defaultArch, "Type of architecture to use, e.g. x86_64, aarch64") cpus := flags.String("cpus", "1", "Number of CPUs") mem := flags.String("mem", "1024", "Amount of memory in MB") @@ -185,8 +179,8 @@ func runQemu(args []string) { // These envvars override the corresponding command line // options. So this must remain after the `flags.Parse` above. - envOverrideBool("LINUXKIT_QEMU_KVM", enableKVM) - envOverrideBool("LINUXKIT_QEMU_CONTAINERIZED", qemuContainerized) + *accel = getStringValue("LINUXKIT_QEMU_ACCEL", *accel, "") + *qemuContainerized = getBoolValue("LINUXKIT_QEMU_CONTAINERIZED", *qemuContainerized) if len(remArgs) == 0 { fmt.Println("Please specify the path to the image to boot") @@ -310,7 +304,7 @@ func runQemu(args []string) { Arch: *arch, CPUs: *cpus, Memory: *mem, - KVM: *enableKVM, + Accel: *accel, Containerized: *qemuContainerized, QemuBinPath: *qemuCmd, PublishedPorts: publishFlags, @@ -429,7 +423,7 @@ func runQemuContainer(config QemuConfig) error { dockerArgs = append(dockerArgs, "--tty") } - if config.KVM { + if strings.Contains(config.Accel, "kvm") { dockerArgs = append(dockerArgs, "--device", "/dev/kvm") } @@ -491,6 +485,7 @@ func buildQemuCmdline(config QemuConfig) (QemuConfig, []string) { qemuArgs = append(qemuArgs, "-m", config.Memory) qemuArgs = append(qemuArgs, "-uuid", config.UUID.String()) qemuArgs = append(qemuArgs, "-pidfile", filepath.Join(config.StatePath, "qemu.pid")) + // Need to specify the vcpu type when running qemu on arm64 platform, for security reason, // the vcpu should be "host" instead of other names such as "cortex-a53"... if config.Arch == "aarch64" { @@ -501,12 +496,27 @@ func buildQemuCmdline(config QemuConfig) (QemuConfig, []string) { } } - if config.KVM { - qemuArgs = append(qemuArgs, "-enable-kvm") + // goArch is the GOARCH equivalent of config.Arch + var goArch string + switch config.Arch { + case "aarch64": + goArch = "arm64" + case "x86_64": + goArch = "amd64" + default: + log.Fatalf("%s is an unsupported architecture.") + } + + if goArch != runtime.GOARCH { + log.Infof("Disable acceleration as %s != %s", config.Arch, runtime.GOARCH) + config.Accel = "" + } + + if config.Accel != "" { if config.Arch == "aarch64" { - qemuArgs = append(qemuArgs, "-machine", "virt,gic_version=host") + qemuArgs = append(qemuArgs, "-machine", fmt.Sprintf("virt,gic_version=host,accel=%s", config.Accel)) } else { - qemuArgs = append(qemuArgs, "-machine", "q35,accel=kvm:tcg") + qemuArgs = append(qemuArgs, "-machine", fmt.Sprintf("q35,accel=%s", config.Accel)) } } else { if config.Arch == "aarch64" {