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 <rolf.neugebauer@docker.com>
This commit is contained in:
Rolf Neugebauer 2018-02-01 16:29:38 +00:00
parent c5b3d088b0
commit 5d0e677397

View File

@ -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" {