mirror of
https://github.com/kata-containers/kata-containers.git
synced 2025-06-28 16:27:50 +00:00
Merge pull request #286 from nitkon/master
Enable Kata container on ppc64le arch
This commit is contained in:
commit
2400978f6a
9
Makefile
9
Makefile
@ -61,6 +61,12 @@ ifeq (,$(installing))
|
|||||||
EXTRA_DEPS = clean
|
EXTRA_DEPS = clean
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
ifeq (uncompressed,$(KERNELTYPE))
|
||||||
|
KERNEL_NAME = vmlinux.container
|
||||||
|
else
|
||||||
|
KERNEL_NAME = vmlinuz.container
|
||||||
|
endif
|
||||||
|
|
||||||
LIBEXECDIR := $(PREFIX)/libexec
|
LIBEXECDIR := $(PREFIX)/libexec
|
||||||
SHAREDIR := $(PREFIX)/share
|
SHAREDIR := $(PREFIX)/share
|
||||||
DEFAULTSDIR := $(SHAREDIR)/defaults
|
DEFAULTSDIR := $(SHAREDIR)/defaults
|
||||||
@ -77,7 +83,7 @@ PKGLIBDIR := $(LOCALSTATEDIR)/lib/$(PROJECT_DIR)
|
|||||||
PKGRUNDIR := $(LOCALSTATEDIR)/run/$(PROJECT_DIR)
|
PKGRUNDIR := $(LOCALSTATEDIR)/run/$(PROJECT_DIR)
|
||||||
PKGLIBEXECDIR := $(LIBEXECDIR)/$(PROJECT_DIR)
|
PKGLIBEXECDIR := $(LIBEXECDIR)/$(PROJECT_DIR)
|
||||||
|
|
||||||
KERNELPATH := $(PKGDATADIR)/vmlinuz.container
|
KERNELPATH := $(PKGDATADIR)/$(KERNEL_NAME)
|
||||||
INITRDPATH := $(PKGDATADIR)/$(INITRDNAME)
|
INITRDPATH := $(PKGDATADIR)/$(INITRDNAME)
|
||||||
IMAGEPATH := $(PKGDATADIR)/$(IMAGENAME)
|
IMAGEPATH := $(PKGDATADIR)/$(IMAGENAME)
|
||||||
FIRMWAREPATH :=
|
FIRMWAREPATH :=
|
||||||
@ -150,6 +156,7 @@ USER_VARS += INITRDNAME
|
|||||||
USER_VARS += INITRDPATH
|
USER_VARS += INITRDPATH
|
||||||
USER_VARS += MACHINETYPE
|
USER_VARS += MACHINETYPE
|
||||||
USER_VARS += KERNELPATH
|
USER_VARS += KERNELPATH
|
||||||
|
USER_VARS += KERNELTYPE
|
||||||
USER_VARS += FIRMWAREPATH
|
USER_VARS += FIRMWAREPATH
|
||||||
USER_VARS += MACHINEACCELERATORS
|
USER_VARS += MACHINEACCELERATORS
|
||||||
USER_VARS += KERNELPARAMS
|
USER_VARS += KERNELPARAMS
|
||||||
|
12
arch/ppc64le-options.mk
Normal file
12
arch/ppc64le-options.mk
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
# Copyright (c) 2018 IBM
|
||||||
|
#
|
||||||
|
# SPDX-License-Identifier: Apache-2.0
|
||||||
|
#
|
||||||
|
|
||||||
|
# Power ppc64le settings
|
||||||
|
|
||||||
|
MACHINETYPE := pseries
|
||||||
|
KERNELPARAMS :=
|
||||||
|
MACHINEACCELERATORS :=
|
||||||
|
KERNELTYPE := uncompressed #This architecture must use an uncompressed kernel.
|
||||||
|
QEMUCMD := qemu-system-ppc64le
|
@ -7,6 +7,13 @@
|
|||||||
|
|
||||||
package main
|
package main
|
||||||
|
|
||||||
|
/*
|
||||||
|
#include <linux/kvm.h>
|
||||||
|
|
||||||
|
const int ioctl_KVM_CREATE_VM = KVM_CREATE_VM;
|
||||||
|
*/
|
||||||
|
import "C"
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"os"
|
"os"
|
||||||
@ -14,6 +21,7 @@ import (
|
|||||||
"path/filepath"
|
"path/filepath"
|
||||||
"regexp"
|
"regexp"
|
||||||
"strings"
|
"strings"
|
||||||
|
"syscall"
|
||||||
|
|
||||||
vc "github.com/kata-containers/runtime/virtcontainers"
|
vc "github.com/kata-containers/runtime/virtcontainers"
|
||||||
"github.com/sirupsen/logrus"
|
"github.com/sirupsen/logrus"
|
||||||
@ -51,6 +59,11 @@ var (
|
|||||||
modInfoCmd = "modinfo"
|
modInfoCmd = "modinfo"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// variables rather than consts to allow tests to modify them
|
||||||
|
var (
|
||||||
|
kvmDevice = "/dev/kvm"
|
||||||
|
)
|
||||||
|
|
||||||
// getCPUInfo returns details of the first CPU read from the specified cpuinfo file
|
// getCPUInfo returns details of the first CPU read from the specified cpuinfo file
|
||||||
func getCPUInfo(cpuInfoFile string) (string, error) {
|
func getCPUInfo(cpuInfoFile string) (string, error) {
|
||||||
text, err := getFileContents(cpuInfoFile)
|
text, err := getFileContents(cpuInfoFile)
|
||||||
@ -222,9 +235,9 @@ func checkKernelModules(modules map[string]kernelModule, handler kernelParamHand
|
|||||||
return count, nil
|
return count, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// hostIsVMContainerCapable checks to see if the host is theoretically capable
|
// genericHostIsVMContainerCapable checks to see if the host is theoretically capable
|
||||||
// of creating a VM container.
|
// of creating a VM container.
|
||||||
func hostIsVMContainerCapable(details vmContainerCapableDetails) error {
|
func genericHostIsVMContainerCapable(details vmContainerCapableDetails) error {
|
||||||
cpuinfo, err := getCPUInfo(details.cpuInfoFile)
|
cpuinfo, err := getCPUInfo(details.cpuInfoFile)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
@ -293,3 +306,58 @@ var kataCheckCLICommand = cli.Command{
|
|||||||
return nil
|
return nil
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func genericArchKernelParamHandler(onVMM bool, fields logrus.Fields, msg string) bool {
|
||||||
|
param, ok := fields["parameter"].(string)
|
||||||
|
if !ok {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
// This option is not required when
|
||||||
|
// already running under a hypervisor.
|
||||||
|
if param == "unrestricted_guest" && onVMM {
|
||||||
|
kataLog.WithFields(fields).Warn(kernelPropertyCorrect)
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
if param == "nested" {
|
||||||
|
kataLog.WithFields(fields).Warn(msg)
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
// don't ignore the error
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
// genericKvmIsUsable determines if it will be possible to create a full virtual machine
|
||||||
|
// by creating a minimal VM and then deleting it.
|
||||||
|
func genericKvmIsUsable() error {
|
||||||
|
flags := syscall.O_RDWR | syscall.O_CLOEXEC
|
||||||
|
|
||||||
|
f, err := syscall.Open(kvmDevice, flags, 0)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
defer syscall.Close(f)
|
||||||
|
|
||||||
|
fieldLogger := kataLog.WithField("check-type", "full")
|
||||||
|
|
||||||
|
fieldLogger.WithField("device", kvmDevice).Info("device available")
|
||||||
|
|
||||||
|
vm, _, errno := syscall.Syscall(syscall.SYS_IOCTL,
|
||||||
|
uintptr(f),
|
||||||
|
uintptr(C.ioctl_KVM_CREATE_VM),
|
||||||
|
0)
|
||||||
|
if errno != 0 {
|
||||||
|
if errno == syscall.EBUSY {
|
||||||
|
fieldLogger.WithField("reason", "another hypervisor running").Error("cannot create VM")
|
||||||
|
}
|
||||||
|
|
||||||
|
return errno
|
||||||
|
}
|
||||||
|
defer syscall.Close(int(vm))
|
||||||
|
|
||||||
|
fieldLogger.WithField("feature", "create-vm").Info("feature available")
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
@ -5,24 +5,10 @@
|
|||||||
|
|
||||||
package main
|
package main
|
||||||
|
|
||||||
/*
|
|
||||||
#include <linux/kvm.h>
|
|
||||||
|
|
||||||
const int ioctl_KVM_CREATE_VM = KVM_CREATE_VM;
|
|
||||||
*/
|
|
||||||
import "C"
|
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"syscall"
|
|
||||||
|
|
||||||
"github.com/sirupsen/logrus"
|
"github.com/sirupsen/logrus"
|
||||||
)
|
)
|
||||||
|
|
||||||
// variables rather than consts to allow tests to modify them
|
|
||||||
var (
|
|
||||||
kvmDevice = "/dev/kvm"
|
|
||||||
)
|
|
||||||
|
|
||||||
// archRequiredCPUFlags maps a CPU flag value to search for and a
|
// archRequiredCPUFlags maps a CPU flag value to search for and a
|
||||||
// human-readable description of that value.
|
// human-readable description of that value.
|
||||||
var archRequiredCPUFlags = map[string]string{
|
var archRequiredCPUFlags = map[string]string{
|
||||||
@ -66,58 +52,19 @@ var archRequiredKernelModules = map[string]kernelModule{
|
|||||||
// kvmIsUsable determines if it will be possible to create a full virtual machine
|
// kvmIsUsable determines if it will be possible to create a full virtual machine
|
||||||
// by creating a minimal VM and then deleting it.
|
// by creating a minimal VM and then deleting it.
|
||||||
func kvmIsUsable() error {
|
func kvmIsUsable() error {
|
||||||
flags := syscall.O_RDWR | syscall.O_CLOEXEC
|
return genericKvmIsUsable()
|
||||||
|
|
||||||
f, err := syscall.Open(kvmDevice, flags, 0)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
defer syscall.Close(f)
|
|
||||||
|
|
||||||
fieldLogger := kataLog.WithField("check-type", "full")
|
|
||||||
|
|
||||||
fieldLogger.WithField("device", kvmDevice).Info("device available")
|
|
||||||
|
|
||||||
vm, _, errno := syscall.Syscall(syscall.SYS_IOCTL,
|
|
||||||
uintptr(f),
|
|
||||||
uintptr(C.ioctl_KVM_CREATE_VM),
|
|
||||||
0)
|
|
||||||
if errno != 0 {
|
|
||||||
if errno == syscall.EBUSY {
|
|
||||||
fieldLogger.WithField("reason", "another hypervisor running").Error("cannot create VM")
|
|
||||||
}
|
|
||||||
|
|
||||||
return errno
|
|
||||||
}
|
|
||||||
defer syscall.Close(int(vm))
|
|
||||||
|
|
||||||
fieldLogger.WithField("feature", "create-vm").Info("feature available")
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func archHostCanCreateVMContainer() error {
|
func archHostCanCreateVMContainer() error {
|
||||||
return kvmIsUsable()
|
return kvmIsUsable()
|
||||||
}
|
}
|
||||||
|
|
||||||
func archKernelParamHandler(onVMM bool, fields logrus.Fields, msg string) bool {
|
// hostIsVMContainerCapable checks to see if the host is theoretically capable
|
||||||
param, ok := fields["parameter"].(string)
|
// of creating a VM container.
|
||||||
if !ok {
|
func hostIsVMContainerCapable(details vmContainerCapableDetails) error {
|
||||||
return false
|
return genericHostIsVMContainerCapable(details)
|
||||||
}
|
}
|
||||||
|
|
||||||
// This option is not required when
|
func archKernelParamHandler(onVMM bool, fields logrus.Fields, msg string) bool {
|
||||||
// already running under a hypervisor.
|
return genericArchKernelParamHandler(onVMM, fields, msg)
|
||||||
if param == "unrestricted_guest" && onVMM {
|
|
||||||
kataLog.WithFields(fields).Warn(kernelPropertyCorrect)
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
if param == "nested" {
|
|
||||||
kataLog.WithFields(fields).Warn(msg)
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
// don't ignore the error
|
|
||||||
return false
|
|
||||||
}
|
}
|
||||||
|
22
cli/kata-check_arm64.go
Normal file
22
cli/kata-check_arm64.go
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
// Copyright (c) 2018 Intel Corporation
|
||||||
|
//
|
||||||
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
//
|
||||||
|
|
||||||
|
package main
|
||||||
|
|
||||||
|
// kvmIsUsable determines if it will be possible to create a full virtual machine
|
||||||
|
// by creating a minimal VM and then deleting it.
|
||||||
|
func kvmIsUsable() error {
|
||||||
|
return genericKvmIsUsable()
|
||||||
|
}
|
||||||
|
|
||||||
|
func archHostCanCreateVMContainer() error {
|
||||||
|
return kvmIsUsable()
|
||||||
|
}
|
||||||
|
|
||||||
|
// hostIsVMContainerCapable checks to see if the host is theoretically capable
|
||||||
|
// of creating a VM container.
|
||||||
|
func hostIsVMContainerCapable(details vmContainerCapableDetails) error {
|
||||||
|
return genericHostIsVMContainerCapable(details)
|
||||||
|
}
|
114
cli/kata-check_data_ppc64le_test.go
Normal file
114
cli/kata-check_data_ppc64le_test.go
Normal file
@ -0,0 +1,114 @@
|
|||||||
|
// Copyright (c) 2018 IBM
|
||||||
|
//
|
||||||
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
//
|
||||||
|
|
||||||
|
package main
|
||||||
|
|
||||||
|
const testCPUInfoTemplate = `
|
||||||
|
processor : 0
|
||||||
|
cpu : POWER8E (raw), altivec supported
|
||||||
|
clock : 3690.000000MHz
|
||||||
|
revision : 2.1 (pvr 004b 0201)
|
||||||
|
|
||||||
|
processor : 8
|
||||||
|
cpu : POWER8E (raw), altivec supported
|
||||||
|
clock : 3690.000000MHz
|
||||||
|
revision : 2.1 (pvr 004b 0201)
|
||||||
|
|
||||||
|
processor : 16
|
||||||
|
cpu : POWER8E (raw), altivec supported
|
||||||
|
clock : 2360.000000MHz
|
||||||
|
revision : 2.1 (pvr 004b 0201)
|
||||||
|
|
||||||
|
processor : 24
|
||||||
|
cpu : POWER8E (raw), altivec supported
|
||||||
|
clock : 2061.000000MHz
|
||||||
|
revision : 2.1 (pvr 004b 0201)
|
||||||
|
|
||||||
|
processor : 32
|
||||||
|
cpu : POWER8E (raw), altivec supported
|
||||||
|
clock : 3690.000000MHz
|
||||||
|
revision : 2.1 (pvr 004b 0201)
|
||||||
|
|
||||||
|
processor : 40
|
||||||
|
cpu : POWER8E (raw), altivec supported
|
||||||
|
clock : 3690.000000MHz
|
||||||
|
revision : 2.1 (pvr 004b 0201)
|
||||||
|
|
||||||
|
processor : 48
|
||||||
|
cpu : POWER8E (raw), altivec supported
|
||||||
|
clock : 3690.000000MHz
|
||||||
|
revision : 2.1 (pvr 004b 0201)
|
||||||
|
|
||||||
|
processor : 56
|
||||||
|
cpu : POWER8E (raw), altivec supported
|
||||||
|
clock : 3690.000000MHz
|
||||||
|
revision : 2.1 (pvr 004b 0201)
|
||||||
|
|
||||||
|
processor : 64
|
||||||
|
cpu : POWER8E (raw), altivec supported
|
||||||
|
clock : 3690.000000MHz
|
||||||
|
revision : 2.1 (pvr 004b 0201)
|
||||||
|
|
||||||
|
processor : 72
|
||||||
|
cpu : POWER8E (raw), altivec supported
|
||||||
|
clock : 3059.000000MHz
|
||||||
|
revision : 2.1 (pvr 004b 0201)
|
||||||
|
|
||||||
|
processor : 80
|
||||||
|
cpu : POWER8E (raw), altivec supported
|
||||||
|
clock : 2693.000000MHz
|
||||||
|
revision : 2.1 (pvr 004b 0201)
|
||||||
|
|
||||||
|
processor : 88
|
||||||
|
cpu : POWER8E (raw), altivec supported
|
||||||
|
clock : 2061.000000MHz
|
||||||
|
revision : 2.1 (pvr 004b 0201)
|
||||||
|
|
||||||
|
processor : 96
|
||||||
|
cpu : POWER8E (raw), altivec supported
|
||||||
|
clock : 3690.000000MHz
|
||||||
|
revision : 2.1 (pvr 004b 0201)
|
||||||
|
|
||||||
|
processor : 104
|
||||||
|
cpu : POWER8E (raw), altivec supported
|
||||||
|
clock : 2061.000000MHz
|
||||||
|
revision : 2.1 (pvr 004b 0201)
|
||||||
|
|
||||||
|
processor : 112
|
||||||
|
cpu : POWER8E (raw), altivec supported
|
||||||
|
clock : 2061.000000MHz
|
||||||
|
revision : 2.1 (pvr 004b 0201)
|
||||||
|
|
||||||
|
processor : 120
|
||||||
|
cpu : POWER8E (raw), altivec supported
|
||||||
|
clock : 2061.000000MHz
|
||||||
|
revision : 2.1 (pvr 004b 0201)
|
||||||
|
|
||||||
|
processor : 128
|
||||||
|
cpu : POWER8E (raw), altivec supported
|
||||||
|
clock : 3690.000000MHz
|
||||||
|
revision : 2.1 (pvr 004b 0201)
|
||||||
|
|
||||||
|
processor : 136
|
||||||
|
cpu : POWER8E (raw), altivec supported
|
||||||
|
clock : 2061.000000MHz
|
||||||
|
revision : 2.1 (pvr 004b 0201)
|
||||||
|
|
||||||
|
processor : 144
|
||||||
|
cpu : POWER8E (raw), altivec supported
|
||||||
|
clock : 2294.000000MHz
|
||||||
|
revision : 2.1 (pvr 004b 0201)
|
||||||
|
|
||||||
|
processor : 152
|
||||||
|
cpu : POWER8E (raw), altivec supported
|
||||||
|
clock : 2560.000000MHz
|
||||||
|
revision : 2.1 (pvr 004b 0201)
|
||||||
|
|
||||||
|
timebase : 512000000
|
||||||
|
platform : PowerNV
|
||||||
|
model : 8247-22L
|
||||||
|
machine : PowerNV 8247-22L
|
||||||
|
firmware : OPAL v3
|
||||||
|
`
|
65
cli/kata-check_ppc64le.go
Normal file
65
cli/kata-check_ppc64le.go
Normal file
@ -0,0 +1,65 @@
|
|||||||
|
// Copyright (c) 2018 IBM
|
||||||
|
//
|
||||||
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
//
|
||||||
|
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"github.com/sirupsen/logrus"
|
||||||
|
)
|
||||||
|
|
||||||
|
// archRequiredCPUFlags maps a CPU flag value to search for and a
|
||||||
|
// human-readable description of that value.
|
||||||
|
var archRequiredCPUFlags = map[string]string{}
|
||||||
|
|
||||||
|
// archRequiredCPUAttribs maps a CPU (non-CPU flag) attribute value to search for
|
||||||
|
// and a human-readable description of that value.
|
||||||
|
var archRequiredCPUAttribs = map[string]string{}
|
||||||
|
|
||||||
|
// archRequiredKernelModules maps a required module name to a human-readable
|
||||||
|
// description of the modules functionality and an optional list of
|
||||||
|
// required module parameters.
|
||||||
|
var archRequiredKernelModules = map[string]kernelModule{
|
||||||
|
"kvm": {
|
||||||
|
desc: "Kernel-based Virtual Machine",
|
||||||
|
},
|
||||||
|
"kvm_hv": {
|
||||||
|
desc: "Kernel-based Virtual Machine hardware virtualization",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
func archHostCanCreateVMContainer() error {
|
||||||
|
return kvmIsUsable()
|
||||||
|
}
|
||||||
|
|
||||||
|
// hostIsVMContainerCapable checks to see if the host is theoretically capable
|
||||||
|
// of creating a VM container.
|
||||||
|
func hostIsVMContainerCapable(details vmContainerCapableDetails) error {
|
||||||
|
_, err := getCPUInfo(details.cpuInfoFile)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
count, err := checkKernelModules(details.requiredKernelModules, archKernelParamHandler)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if count == 0 {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
return fmt.Errorf("ERROR: %s", failMessage)
|
||||||
|
}
|
||||||
|
|
||||||
|
// kvmIsUsable determines if it will be possible to create a full virtual machine
|
||||||
|
// by creating a minimal VM and then deleting it.
|
||||||
|
func kvmIsUsable() error {
|
||||||
|
return genericKvmIsUsable()
|
||||||
|
}
|
||||||
|
|
||||||
|
func archKernelParamHandler(onVMM bool, fields logrus.Fields, msg string) bool {
|
||||||
|
return genericArchKernelParamHandler(onVMM, fields, msg)
|
||||||
|
}
|
@ -15,6 +15,7 @@ import (
|
|||||||
"github.com/kata-containers/runtime/virtcontainers/pkg/oci"
|
"github.com/kata-containers/runtime/virtcontainers/pkg/oci"
|
||||||
specs "github.com/opencontainers/runtime-spec/specs-go"
|
specs "github.com/opencontainers/runtime-spec/specs-go"
|
||||||
"github.com/urfave/cli"
|
"github.com/urfave/cli"
|
||||||
|
runtim "runtime"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Semantic version for the output of the command.
|
// Semantic version for the output of the command.
|
||||||
@ -173,6 +174,9 @@ func getHostInfo() (HostInfo, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
hostVMContainerCapable := true
|
hostVMContainerCapable := true
|
||||||
|
if runtim.GOARCH == "ppc64le" {
|
||||||
|
hostVMContainerCapable = false
|
||||||
|
}
|
||||||
|
|
||||||
details := vmContainerCapableDetails{
|
details := vmContainerCapableDetails{
|
||||||
cpuInfoFile: procCPUInfo,
|
cpuInfoFile: procCPUInfo,
|
||||||
|
@ -443,8 +443,8 @@ func getHostMemorySizeKb(memInfoPath string) (uint64, error) {
|
|||||||
|
|
||||||
// RunningOnVMM checks if the system is running inside a VM.
|
// RunningOnVMM checks if the system is running inside a VM.
|
||||||
func RunningOnVMM(cpuInfoPath string) (bool, error) {
|
func RunningOnVMM(cpuInfoPath string) (bool, error) {
|
||||||
if runtime.GOARCH == "arm64" {
|
if runtime.GOARCH == "arm64" || runtime.GOARCH == "ppc64le" {
|
||||||
virtLog.Debugf("Unable to know if the system is running inside a VM")
|
virtLog.Info("Unable to know if the system is running inside a VM")
|
||||||
return false, nil
|
return false, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -11,6 +11,7 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
@ -926,3 +927,82 @@ func (q *qemu) addDevice(devInfo interface{}, devType deviceType) error {
|
|||||||
func (q *qemu) getSandboxConsole(sandboxID string) (string, error) {
|
func (q *qemu) getSandboxConsole(sandboxID string) (string, error) {
|
||||||
return utils.BuildSocketPath(runStoragePath, sandboxID, defaultConsole)
|
return utils.BuildSocketPath(runStoragePath, sandboxID, defaultConsole)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// genericAppendBridges appends to devices the given bridges
|
||||||
|
func genericAppendBridges(devices []govmmQemu.Device, bridges []Bridge, machineType string) []govmmQemu.Device {
|
||||||
|
bus := defaultPCBridgeBus
|
||||||
|
if machineType == QemuQ35 {
|
||||||
|
bus = defaultBridgeBus
|
||||||
|
}
|
||||||
|
|
||||||
|
for idx, b := range bridges {
|
||||||
|
t := govmmQemu.PCIBridge
|
||||||
|
if b.Type == pcieBridge {
|
||||||
|
t = govmmQemu.PCIEBridge
|
||||||
|
}
|
||||||
|
|
||||||
|
bridges[idx].Addr = bridgePCIStartAddr + idx
|
||||||
|
|
||||||
|
devices = append(devices,
|
||||||
|
govmmQemu.BridgeDevice{
|
||||||
|
Type: t,
|
||||||
|
Bus: bus,
|
||||||
|
ID: b.ID,
|
||||||
|
// Each bridge is required to be assigned a unique chassis id > 0
|
||||||
|
Chassis: (idx + 1),
|
||||||
|
SHPC: true,
|
||||||
|
Addr: strconv.FormatInt(int64(bridges[idx].Addr), 10),
|
||||||
|
},
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
return devices
|
||||||
|
}
|
||||||
|
|
||||||
|
func genericBridges(number uint32, machineType string) []Bridge {
|
||||||
|
var bridges []Bridge
|
||||||
|
var bt bridgeType
|
||||||
|
|
||||||
|
switch machineType {
|
||||||
|
|
||||||
|
case QemuQ35:
|
||||||
|
// currently only pci bridges are supported
|
||||||
|
// qemu-2.10 will introduce pcie bridges
|
||||||
|
fallthrough
|
||||||
|
case QemuPC:
|
||||||
|
bt = pciBridge
|
||||||
|
case QemuPseries:
|
||||||
|
bt = pciBridge
|
||||||
|
default:
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
for i := uint32(0); i < number; i++ {
|
||||||
|
bridges = append(bridges, Bridge{
|
||||||
|
Type: bt,
|
||||||
|
ID: fmt.Sprintf("%s-bridge-%d", bt, i),
|
||||||
|
Address: make(map[uint32]string),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
return bridges
|
||||||
|
}
|
||||||
|
|
||||||
|
func genericMemoryTopology(memoryMb, hostMemoryMb uint64) govmmQemu.Memory {
|
||||||
|
// NVDIMM device needs memory space 1024MB
|
||||||
|
// See https://github.com/clearcontainers/runtime/issues/380
|
||||||
|
memoryOffset := 1024
|
||||||
|
|
||||||
|
// add 1G memory space for nvdimm device (vm guest image)
|
||||||
|
memMax := fmt.Sprintf("%dM", hostMemoryMb+uint64(memoryOffset))
|
||||||
|
|
||||||
|
mem := fmt.Sprintf("%dM", memoryMb)
|
||||||
|
|
||||||
|
memory := govmmQemu.Memory{
|
||||||
|
Size: mem,
|
||||||
|
Slots: defaultMemSlots,
|
||||||
|
MaxMem: memMax,
|
||||||
|
}
|
||||||
|
|
||||||
|
return memory
|
||||||
|
}
|
||||||
|
@ -6,9 +6,7 @@
|
|||||||
package virtcontainers
|
package virtcontainers
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
|
||||||
"os"
|
"os"
|
||||||
"strconv"
|
|
||||||
|
|
||||||
govmmQemu "github.com/intel/govmm/qemu"
|
govmmQemu "github.com/intel/govmm/qemu"
|
||||||
)
|
)
|
||||||
@ -93,12 +91,7 @@ func newQemuArch(config HypervisorConfig) qemuArch {
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
if config.ImagePath != "" {
|
q.handleImagePath(config)
|
||||||
q.kernelParams = append(q.kernelParams, kernelRootParams...)
|
|
||||||
q.kernelParamsNonDebug = append(q.kernelParamsNonDebug, kernelParamsSystemdNonDebug...)
|
|
||||||
q.kernelParamsDebug = append(q.kernelParamsDebug, kernelParamsSystemdDebug...)
|
|
||||||
}
|
|
||||||
|
|
||||||
return q
|
return q
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -114,29 +107,7 @@ func (q *qemuAmd64) capabilities() capabilities {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (q *qemuAmd64) bridges(number uint32) []Bridge {
|
func (q *qemuAmd64) bridges(number uint32) []Bridge {
|
||||||
var bridges []Bridge
|
return genericBridges(number, q.machineType)
|
||||||
var bt bridgeType
|
|
||||||
|
|
||||||
switch q.machineType {
|
|
||||||
case QemuQ35:
|
|
||||||
// currently only pci bridges are supported
|
|
||||||
// qemu-2.10 will introduce pcie bridges
|
|
||||||
fallthrough
|
|
||||||
case QemuPC:
|
|
||||||
bt = pciBridge
|
|
||||||
default:
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
for i := uint32(0); i < number; i++ {
|
|
||||||
bridges = append(bridges, Bridge{
|
|
||||||
Type: bt,
|
|
||||||
ID: fmt.Sprintf("%s-bridge-%d", bt, i),
|
|
||||||
Address: make(map[uint32]string),
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
return bridges
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (q *qemuAmd64) cpuModel() string {
|
func (q *qemuAmd64) cpuModel() string {
|
||||||
@ -148,22 +119,7 @@ func (q *qemuAmd64) cpuModel() string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (q *qemuAmd64) memoryTopology(memoryMb, hostMemoryMb uint64) govmmQemu.Memory {
|
func (q *qemuAmd64) memoryTopology(memoryMb, hostMemoryMb uint64) govmmQemu.Memory {
|
||||||
// NVDIMM device needs memory space 1024MB
|
return genericMemoryTopology(memoryMb, hostMemoryMb)
|
||||||
// See https://github.com/clearcontainers/runtime/issues/380
|
|
||||||
memoryOffset := 1024
|
|
||||||
|
|
||||||
// add 1G memory space for nvdimm device (vm guest image)
|
|
||||||
memMax := fmt.Sprintf("%dM", hostMemoryMb+uint64(memoryOffset))
|
|
||||||
|
|
||||||
mem := fmt.Sprintf("%dM", memoryMb)
|
|
||||||
|
|
||||||
memory := govmmQemu.Memory{
|
|
||||||
Size: mem,
|
|
||||||
Slots: defaultMemSlots,
|
|
||||||
MaxMem: memMax,
|
|
||||||
}
|
|
||||||
|
|
||||||
return memory
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (q *qemuAmd64) appendImage(devices []govmmQemu.Device, path string) ([]govmmQemu.Device, error) {
|
func (q *qemuAmd64) appendImage(devices []govmmQemu.Device, path string) ([]govmmQemu.Device, error) {
|
||||||
@ -194,31 +150,5 @@ func (q *qemuAmd64) appendImage(devices []govmmQemu.Device, path string) ([]govm
|
|||||||
|
|
||||||
// appendBridges appends to devices the given bridges
|
// appendBridges appends to devices the given bridges
|
||||||
func (q *qemuAmd64) appendBridges(devices []govmmQemu.Device, bridges []Bridge) []govmmQemu.Device {
|
func (q *qemuAmd64) appendBridges(devices []govmmQemu.Device, bridges []Bridge) []govmmQemu.Device {
|
||||||
bus := defaultPCBridgeBus
|
return genericAppendBridges(devices, bridges, q.machineType)
|
||||||
if q.machineType == QemuQ35 {
|
|
||||||
bus = defaultBridgeBus
|
|
||||||
}
|
|
||||||
|
|
||||||
for idx, b := range bridges {
|
|
||||||
t := govmmQemu.PCIBridge
|
|
||||||
if b.Type == pcieBridge {
|
|
||||||
t = govmmQemu.PCIEBridge
|
|
||||||
}
|
|
||||||
|
|
||||||
bridges[idx].Addr = bridgePCIStartAddr + idx
|
|
||||||
|
|
||||||
devices = append(devices,
|
|
||||||
govmmQemu.BridgeDevice{
|
|
||||||
Type: t,
|
|
||||||
Bus: bus,
|
|
||||||
ID: b.ID,
|
|
||||||
// Each bridge is required to be assigned a unique chassis id > 0
|
|
||||||
Chassis: (idx + 1),
|
|
||||||
SHPC: true,
|
|
||||||
Addr: strconv.FormatInt(int64(bridges[idx].Addr), 10),
|
|
||||||
},
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
return devices
|
|
||||||
}
|
}
|
||||||
|
@ -82,6 +82,9 @@ type qemuArch interface {
|
|||||||
|
|
||||||
// appendVFIODevice appends a VFIO device to devices
|
// appendVFIODevice appends a VFIO device to devices
|
||||||
appendVFIODevice(devices []govmmQemu.Device, vfioDevice drivers.VFIODevice) []govmmQemu.Device
|
appendVFIODevice(devices []govmmQemu.Device, vfioDevice drivers.VFIODevice) []govmmQemu.Device
|
||||||
|
|
||||||
|
// handleImagePath handles the Hypervisor Config image path
|
||||||
|
handleImagePath(config HypervisorConfig)
|
||||||
}
|
}
|
||||||
|
|
||||||
type qemuArchBase struct {
|
type qemuArchBase struct {
|
||||||
@ -131,6 +134,9 @@ const (
|
|||||||
|
|
||||||
// QemuVirt is the QEMU virt machine type for aarch64
|
// QemuVirt is the QEMU virt machine type for aarch64
|
||||||
QemuVirt = "virt"
|
QemuVirt = "virt"
|
||||||
|
|
||||||
|
// QemuPseries is a QEMU virt machine type for for ppc64le
|
||||||
|
QemuPseries = "pseries"
|
||||||
)
|
)
|
||||||
|
|
||||||
// kernelParamsNonDebug is a list of the default kernel
|
// kernelParamsNonDebug is a list of the default kernel
|
||||||
@ -495,3 +501,11 @@ func (q *qemuArchBase) appendVFIODevice(devices []govmmQemu.Device, vfioDevice d
|
|||||||
|
|
||||||
return devices
|
return devices
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (q *qemuArchBase) handleImagePath(config HypervisorConfig) {
|
||||||
|
if config.ImagePath != "" {
|
||||||
|
q.kernelParams = append(q.kernelParams, kernelRootParams...)
|
||||||
|
q.kernelParamsNonDebug = append(q.kernelParamsNonDebug, kernelParamsSystemdNonDebug...)
|
||||||
|
q.kernelParamsDebug = append(q.kernelParamsDebug, kernelParamsSystemdDebug...)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
52
virtcontainers/qemu_arm64_test.go
Normal file
52
virtcontainers/qemu_arm64_test.go
Normal file
@ -0,0 +1,52 @@
|
|||||||
|
// Copyright (c) 2018 IBM
|
||||||
|
//
|
||||||
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
//
|
||||||
|
|
||||||
|
package virtcontainers
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
govmmQemu "github.com/intel/govmm/qemu"
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
|
)
|
||||||
|
|
||||||
|
func newTestQemu(machineType string) qemuArch {
|
||||||
|
config := HypervisorConfig{
|
||||||
|
HypervisorMachineType: machineType,
|
||||||
|
}
|
||||||
|
return newQemuArch(config)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestQemuArm64CPUModel(t *testing.T) {
|
||||||
|
assert := assert.New(t)
|
||||||
|
arm64 := newTestQemu(virt)
|
||||||
|
|
||||||
|
expectedOut := defaultCPUModel
|
||||||
|
model := arm64.cpuModel()
|
||||||
|
assert.Equal(expectedOut, model)
|
||||||
|
|
||||||
|
arm64.enableNestingChecks()
|
||||||
|
expectedOut = defaultCPUModel + ",pmu=off"
|
||||||
|
model = arm64.cpuModel()
|
||||||
|
assert.Equal(expectedOut, model)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestQemuArm64MemoryTopology(t *testing.T) {
|
||||||
|
assert := assert.New(t)
|
||||||
|
arm64 := newTestQemu(virt)
|
||||||
|
memoryOffset := 1024
|
||||||
|
|
||||||
|
hostMem := uint64(1024)
|
||||||
|
mem := uint64(120)
|
||||||
|
expectedMemory := govmmQemu.Memory{
|
||||||
|
Size: fmt.Sprintf("%dM", mem),
|
||||||
|
Slots: defaultMemSlots,
|
||||||
|
MaxMem: fmt.Sprintf("%dM", hostMem+uint64(memoryOffset)),
|
||||||
|
}
|
||||||
|
|
||||||
|
m := arm64.memoryTopology(mem, hostMem)
|
||||||
|
assert.Equal(expectedMemory, m)
|
||||||
|
}
|
137
virtcontainers/qemu_ppc64le.go
Normal file
137
virtcontainers/qemu_ppc64le.go
Normal file
@ -0,0 +1,137 @@
|
|||||||
|
// Copyright (c) 2018 IBM
|
||||||
|
//
|
||||||
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
//
|
||||||
|
|
||||||
|
package virtcontainers
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/hex"
|
||||||
|
"os"
|
||||||
|
|
||||||
|
govmmQemu "github.com/intel/govmm/qemu"
|
||||||
|
"github.com/kata-containers/runtime/virtcontainers/device/drivers"
|
||||||
|
"github.com/kata-containers/runtime/virtcontainers/utils"
|
||||||
|
)
|
||||||
|
|
||||||
|
type qemuPPC64le struct {
|
||||||
|
// inherit from qemuArchBase, overwrite methods if needed
|
||||||
|
qemuArchBase
|
||||||
|
}
|
||||||
|
|
||||||
|
const defaultQemuPath = "/usr/bin/qemu-system-ppc64le"
|
||||||
|
|
||||||
|
const defaultQemuMachineType = QemuPseries
|
||||||
|
|
||||||
|
const defaultQemuMachineOptions = "accel=kvm,usb=off"
|
||||||
|
|
||||||
|
const defaultPCBridgeBus = "pci.0"
|
||||||
|
|
||||||
|
var qemuPaths = map[string]string{
|
||||||
|
QemuPseries: defaultQemuPath,
|
||||||
|
}
|
||||||
|
|
||||||
|
var kernelRootParams = []Param{}
|
||||||
|
|
||||||
|
var kernelParams = []Param{
|
||||||
|
{"tsc", "reliable"},
|
||||||
|
{"no_timer_check", ""},
|
||||||
|
{"rcupdate.rcu_expedited", "1"},
|
||||||
|
{"noreplace-smp", ""},
|
||||||
|
{"reboot", "k"},
|
||||||
|
{"console", "hvc0"},
|
||||||
|
{"console", "hvc1"},
|
||||||
|
{"iommu", "off"},
|
||||||
|
{"cryptomgr.notests", ""},
|
||||||
|
{"net.ifnames", "0"},
|
||||||
|
{"pci", "lastbus=0"},
|
||||||
|
}
|
||||||
|
|
||||||
|
var supportedQemuMachines = []govmmQemu.Machine{
|
||||||
|
{
|
||||||
|
Type: QemuPseries,
|
||||||
|
Options: defaultQemuMachineOptions,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
// returns the maximum number of vCPUs supported
|
||||||
|
func MaxQemuVCPUs() uint32 {
|
||||||
|
return uint32(128)
|
||||||
|
}
|
||||||
|
|
||||||
|
func newQemuArch(config HypervisorConfig) qemuArch {
|
||||||
|
machineType := config.HypervisorMachineType
|
||||||
|
if machineType == "" {
|
||||||
|
machineType = defaultQemuMachineType
|
||||||
|
}
|
||||||
|
|
||||||
|
q := &qemuPPC64le{
|
||||||
|
qemuArchBase{
|
||||||
|
machineType: machineType,
|
||||||
|
qemuPaths: qemuPaths,
|
||||||
|
supportedQemuMachines: supportedQemuMachines,
|
||||||
|
kernelParamsNonDebug: kernelParamsNonDebug,
|
||||||
|
kernelParamsDebug: kernelParamsDebug,
|
||||||
|
kernelParams: kernelParams,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
q.handleImagePath(config)
|
||||||
|
return q
|
||||||
|
}
|
||||||
|
|
||||||
|
func (q *qemuPPC64le) capabilities() capabilities {
|
||||||
|
var caps capabilities
|
||||||
|
|
||||||
|
// pseries machine type supports hotplugging drives
|
||||||
|
if q.machineType == QemuPseries {
|
||||||
|
caps.setBlockDeviceHotplugSupport()
|
||||||
|
}
|
||||||
|
|
||||||
|
return caps
|
||||||
|
}
|
||||||
|
|
||||||
|
func (q *qemuPPC64le) bridges(number uint32) []Bridge {
|
||||||
|
return genericBridges(number, q.machineType)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (q *qemuPPC64le) cpuModel() string {
|
||||||
|
cpuModel := defaultCPUModel
|
||||||
|
if q.nestedRun {
|
||||||
|
cpuModel += ",pmu=off"
|
||||||
|
}
|
||||||
|
return cpuModel
|
||||||
|
}
|
||||||
|
|
||||||
|
func (q *qemuPPC64le) memoryTopology(memoryMb, hostMemoryMb uint64) govmmQemu.Memory {
|
||||||
|
|
||||||
|
// align hostMemoryMb to 256 MB multiples
|
||||||
|
hostMemoryMb -= (hostMemoryMb % 256)
|
||||||
|
return genericMemoryTopology(memoryMb, hostMemoryMb)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (q *qemuPPC64le) appendImage(devices []govmmQemu.Device, path string) ([]govmmQemu.Device, error) {
|
||||||
|
if _, err := os.Stat(path); os.IsNotExist(err) {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
randBytes, err := utils.GenerateRandomBytes(8)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
id := utils.MakeNameID("image", hex.EncodeToString(randBytes), maxDevIDSize)
|
||||||
|
|
||||||
|
drive := drivers.Drive{
|
||||||
|
File: path,
|
||||||
|
Format: "raw",
|
||||||
|
ID: id,
|
||||||
|
}
|
||||||
|
|
||||||
|
return q.appendBlockDevice(devices, drive), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// appendBridges appends to devices the given bridges
|
||||||
|
func (q *qemuPPC64le) appendBridges(devices []govmmQemu.Device, bridges []Bridge) []govmmQemu.Device {
|
||||||
|
return genericAppendBridges(devices, bridges, q.machineType)
|
||||||
|
}
|
52
virtcontainers/qemu_ppc64le_test.go
Normal file
52
virtcontainers/qemu_ppc64le_test.go
Normal file
@ -0,0 +1,52 @@
|
|||||||
|
// Copyright (c) 2018 IBM
|
||||||
|
//
|
||||||
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
//
|
||||||
|
|
||||||
|
package virtcontainers
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
govmmQemu "github.com/intel/govmm/qemu"
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
|
)
|
||||||
|
|
||||||
|
func newTestQemu(machineType string) qemuArch {
|
||||||
|
config := HypervisorConfig{
|
||||||
|
HypervisorMachineType: machineType,
|
||||||
|
}
|
||||||
|
return newQemuArch(config)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestQemuPPC64leCPUModel(t *testing.T) {
|
||||||
|
assert := assert.New(t)
|
||||||
|
ppc64le := newTestQemu(QemuPseries)
|
||||||
|
|
||||||
|
expectedOut := defaultCPUModel
|
||||||
|
model := ppc64le.cpuModel()
|
||||||
|
assert.Equal(expectedOut, model)
|
||||||
|
|
||||||
|
ppc64le.enableNestingChecks()
|
||||||
|
expectedOut = defaultCPUModel + ",pmu=off"
|
||||||
|
model = ppc64le.cpuModel()
|
||||||
|
assert.Equal(expectedOut, model)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestQemuPPC64leMemoryTopology(t *testing.T) {
|
||||||
|
assert := assert.New(t)
|
||||||
|
ppc64le := newTestQemu(QemuPseries)
|
||||||
|
memoryOffset := 1024
|
||||||
|
|
||||||
|
hostMem := uint64(1024)
|
||||||
|
mem := uint64(120)
|
||||||
|
expectedMemory := govmmQemu.Memory{
|
||||||
|
Size: fmt.Sprintf("%dM", mem),
|
||||||
|
Slots: defaultMemSlots,
|
||||||
|
MaxMem: fmt.Sprintf("%dM", hostMem+uint64(memoryOffset)),
|
||||||
|
}
|
||||||
|
|
||||||
|
m := ppc64le.memoryTopology(mem, hostMem)
|
||||||
|
assert.Equal(expectedMemory, m)
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user