Skip to content
This repository has been archived by the owner on Jan 4, 2024. It is now read-only.

Commit

Permalink
qemu/arm64: Detect host GIC version to configure guest GIC
Browse files Browse the repository at this point in the history
QEMU supports GICv2, GICv3 and host parameters for guest
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:
"Unable to determine GIC version supported by host"

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.

Fixes: kata-containers#614

Signed-off-by: Wei Chen <[email protected]>
Signed-off-by: Penny Zheng <[email protected]>
  • Loading branch information
Weichen81 committed Aug 23, 2018
1 parent d6a773c commit b438590
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 b438590

Please sign in to comment.