Files
kata-containers/virtcontainers/qemu_arm64.go
Hui Zhu dd28ff5986 memory: Add new option memory_offset
This value will be plused to max memory of hypervisor.
It is the memory address space for the NVDIMM devie.
If set block storage driver (block_device_driver) to "nvdimm",
should set memory_offset to the size of block device.

Signed-off-by: Hui Zhu <teawater@hyper.sh>
2018-12-24 15:36:25 +08:00

156 lines
3.9 KiB
Go

// Copyright (c) 2018 Intel Corporation
//
// SPDX-License-Identifier: Apache-2.0
//
package virtcontainers
import (
"io/ioutil"
"runtime"
"strings"
govmmQemu "github.com/intel/govmm/qemu"
"github.com/sirupsen/logrus"
)
type qemuArm64 struct {
// inherit from qemuArchBase, overwrite methods if needed
qemuArchBase
}
const defaultQemuPath = "/usr/bin/qemu-system-aarch64"
const defaultQemuMachineType = QemuVirt
var defaultQemuMachineOptions = "usb=off,accel=kvm,gic-version=" + getGuestGICVersion()
// Not used
const defaultPCBridgeBus = ""
var qemuPaths = map[string]string{
QemuVirt: defaultQemuPath,
}
var kernelParams = []Param{
{"console", "hvc0"},
{"console", "hvc1"},
{"iommu.passthrough", "0"},
}
var kernelRootParams = []Param{
{"root", "/dev/vda1"},
}
var supportedQemuMachines = []govmmQemu.Machine{
{
Type: QemuVirt,
Options: defaultQemuMachineOptions,
},
}
// 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"
}
//In qemu, maximum number of vCPUs depends on the GIC version, or on how
//many redistributors we can fit into the memory map.
//related codes are under github.com/qemu/qemu/hw/arm/virt.c(Line 135 and 1306 in stable-2.11)
//for now, qemu only supports v2 and v3, we treat v4 as v3 based on
//backward compatibility.
var gicList = map[uint32]uint32{
uint32(2): uint32(8),
uint32(3): uint32(123),
uint32(4): uint32(123),
}
// MaxQemuVCPUs returns the maximum number of vCPUs supported
func MaxQemuVCPUs() uint32 {
if hostGICVersion != 0 {
return gicList[hostGICVersion]
}
return uint32(runtime.NumCPU())
}
func newQemuArch(config HypervisorConfig) qemuArch {
machineType := config.HypervisorMachineType
if machineType == "" {
machineType = defaultQemuMachineType
}
q := &qemuArm64{
qemuArchBase{
machineType: machineType,
memoryOffset: config.MemOffset,
qemuPaths: qemuPaths,
supportedQemuMachines: supportedQemuMachines,
kernelParamsNonDebug: kernelParamsNonDebug,
kernelParamsDebug: kernelParamsDebug,
kernelParams: kernelParams,
},
}
if config.ImagePath != "" {
q.kernelParams = append(q.kernelParams, kernelRootParams...)
q.kernelParamsNonDebug = append(q.kernelParamsNonDebug, kernelParamsSystemdNonDebug...)
q.kernelParamsDebug = append(q.kernelParamsDebug, kernelParamsSystemdDebug...)
}
return q
}