Skip to content

Commit

Permalink
Merge pull request clearcontainers#616 from Weichen81/master
Browse files Browse the repository at this point in the history
qemu/arm64: Detect host GIC version to configure guest GIC
  • Loading branch information
Julio Montes authored Aug 24, 2018
2 parents ed6f715 + b438590 commit 500d017
Showing 1 changed file with 63 additions and 1 deletion.
64 changes: 63 additions & 1 deletion virtcontainers/qemu_arm64.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,12 @@
package virtcontainers

import (
"io/ioutil"
"runtime"
"strings"

govmmQemu "github.com/intel/govmm/qemu"
"github.com/sirupsen/logrus"
)

type qemuArm64 struct {
Expand All @@ -20,7 +23,7 @@ const defaultQemuPath = "/usr/bin/qemu-system-aarch64"

const defaultQemuMachineType = QemuVirt

const defaultQemuMachineOptions = "gic-version=host,usb=off,accel=kvm"
var defaultQemuMachineOptions = "usb=off,accel=kvm,gic-version=" + getGuestGICVersion()

// Not used
const defaultPCBridgeBus = ""
Expand All @@ -45,6 +48,65 @@ var supportedQemuMachines = []govmmQemu.Machine{
},
}

// Logger returns a logrus logger appropriate for logging qemu-aarch64 messages
func qemuArmLogger() *logrus.Entry {
return virtLog.WithField("subsystem", "qemu-aarch64")
}

// On ARM platform, we have different GIC interrupt controllers. Different
// GIC supports different QEMU parameters for virtual GIC and max VCPUs
var hostGICVersion = getHostGICVersion()

// We will access this file on host to detect host GIC version
var gicProfile = "/proc/interrupts"

// Detect the host GIC version.
// Success: return the number of GIC version
// Failed: return 0
func getHostGICVersion() (version uint32) {
bytes, err := ioutil.ReadFile(gicProfile)
if err != nil {
qemuArmLogger().WithField("GIC profile", gicProfile).WithError(err).Error("Failed to parse GIC profile")
return 0
}

s := string(bytes)
if strings.Contains(s, "GICv2") {
return 2
}

if strings.Contains(s, "GICv3") {
return 3
}

if strings.Contains(s, "GICv4") {
return 4
}

return 0
}

// QEMU supports GICv2, GICv3 and host parameters for gic-version. The host
// parameter will let QEMU detect GIC version by itself. This parameter
// will work properly when host GIC version is GICv2 or GICv3. But the
// detection will failed when host GIC is gicv4 or higher. In this case,
// we have to detect the host GIC version manually and force QEMU to use
// GICv3 when host GIC is GICv4 or higher.
func getGuestGICVersion() (version string) {
if hostGICVersion == 2 {
return "2"
}

if hostGICVersion >= 3 {
return "3"
}

// We can't parse valid host GIC version from GIC profile.
// But we can use "host" to ask QEMU to detect valid GIC
// through KVM API for a try.
return "host"
}

// MaxQemuVCPUs returns the maximum number of vCPUs supported
func MaxQemuVCPUs() uint32 {
return uint32(runtime.NumCPU())
Expand Down

0 comments on commit 500d017

Please sign in to comment.