cli: add AMD support to kata-check

Added support for identifying AMD CPUs in the `kata-check` CLI command.

Signed-off-by: George Kennedy <george.kennedy@oracle.com>

Fixes #476.
This commit is contained in:
George Kennedy 2018-07-25 12:05:47 -04:00
parent 67b5841153
commit 4326ea874a
5 changed files with 163 additions and 50 deletions

View File

@ -283,6 +283,8 @@ var kataCheckCLICommand = cli.Command{
Usage: "tests if system can run " + project, Usage: "tests if system can run " + project,
Action: func(context *cli.Context) error { Action: func(context *cli.Context) error {
setCPUtype()
details := vmContainerCapableDetails{ details := vmContainerCapableDetails{
cpuInfoFile: procCPUInfo, cpuInfoFile: procCPUInfo,
requiredCPUFlags: archRequiredCPUFlags, requiredCPUFlags: archRequiredCPUFlags,

View File

@ -7,34 +7,62 @@ package main
import ( import (
"github.com/sirupsen/logrus" "github.com/sirupsen/logrus"
"io/ioutil"
"strings"
) )
const ( const (
cpuFlagsTag = genericCPUFlagsTag cpuFlagsTag = genericCPUFlagsTag
archCPUVendorField = genericCPUVendorField archCPUVendorField = genericCPUVendorField
archCPUModelField = genericCPUModelField archCPUModelField = genericCPUModelField
archGenuineIntel = "GenuineIntel"
archAuthenticAMD = "AuthenticAMD"
msgKernelVM = "Kernel-based Virtual Machine"
msgKernelVirtio = "Host kernel accelerator for virtio"
msgKernelVirtioNet = "Host kernel accelerator for virtio network"
) )
// CPU types
const (
cpuTypeIntel = 0
cpuTypeAMD = 1
cpuTypeUnknown = -1
)
// cpuType save the CPU type
var cpuType int
// 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
"vmx": "Virtualization support",
"lm": "64Bit CPU",
"sse4_1": "SSE4.1",
}
// archRequiredCPUAttribs maps a CPU (non-CPU flag) attribute value to search for // archRequiredCPUAttribs maps a CPU (non-CPU flag) attribute value to search for
// and a human-readable description of that value. // and a human-readable description of that value.
var archRequiredCPUAttribs = map[string]string{ var archRequiredCPUAttribs map[string]string
"GenuineIntel": "Intel Architecture CPU",
}
// archRequiredKernelModules maps a required module name to a human-readable // archRequiredKernelModules maps a required module name to a human-readable
// description of the modules functionality and an optional list of // description of the modules functionality and an optional list of
// required module parameters. // required module parameters.
var archRequiredKernelModules = map[string]kernelModule{ var archRequiredKernelModules map[string]kernelModule
func setCPUtype() {
cpuType = getCPUtype()
if cpuType == cpuTypeUnknown {
kataLog.Fatal("Unknown CPU Type")
exit(1)
} else if cpuType == cpuTypeIntel {
archRequiredCPUFlags = map[string]string{
"vmx": "Virtualization support",
"lm": "64Bit CPU",
"sse4_1": "SSE4.1",
}
archRequiredCPUAttribs = map[string]string{
archGenuineIntel: "Intel Architecture CPU",
}
archRequiredKernelModules = map[string]kernelModule{
"kvm": { "kvm": {
desc: "Kernel-based Virtual Machine", desc: msgKernelVM,
}, },
"kvm_intel": { "kvm_intel": {
desc: "Intel KVM", desc: "Intel KVM",
@ -48,11 +76,55 @@ var archRequiredKernelModules = map[string]kernelModule{
}, },
}, },
"vhost": { "vhost": {
desc: "Host kernel accelerator for virtio", desc: msgKernelVirtio,
}, },
"vhost_net": { "vhost_net": {
desc: "Host kernel accelerator for virtio network", desc: msgKernelVirtioNet,
}, },
}
} else if cpuType == cpuTypeAMD {
archRequiredCPUFlags = map[string]string{
"svm": "Virtualization support",
"lm": "64Bit CPU",
"sse4_1": "SSE4.1",
}
archRequiredCPUAttribs = map[string]string{
archAuthenticAMD: "AMD Architecture CPU",
}
archRequiredKernelModules = map[string]kernelModule{
"kvm": {
desc: msgKernelVM,
},
"kvm_amd": {
desc: "AMD KVM",
parameters: map[string]string{
"nested": "1",
},
},
"vhost": {
desc: msgKernelVirtio,
},
"vhost_net": {
desc: msgKernelVirtioNet,
},
}
}
}
func getCPUtype() int {
content, err := ioutil.ReadFile("/proc/cpuinfo")
if err != nil {
kataLog.WithError(err).Error("failed to read file")
return cpuTypeUnknown
}
str := string(content)
if strings.Contains(str, archGenuineIntel) {
return cpuTypeIntel
} else if strings.Contains(str, archAuthenticAMD) {
return cpuTypeAMD
} else {
return cpuTypeUnknown
}
} }
// 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

View File

@ -73,14 +73,27 @@ func TestCCCheckCLIFunction(t *testing.T) {
t.Fatal(err) t.Fatal(err)
} }
cpuData := []testCPUData{ var cpuData []testCPUData
{"GenuineIntel", "lm vmx sse4_1", false}, var moduleData []testModuleData
if cpuType == cpuTypeIntel {
cpuData = []testCPUData{
{archGenuineIntel, "lm vmx sse4_1", false},
} }
moduleData := []testModuleData{ moduleData = []testModuleData{
{filepath.Join(sysModuleDir, "kvm_intel/parameters/unrestricted_guest"), false, "Y"}, {filepath.Join(sysModuleDir, "kvm_intel/parameters/unrestricted_guest"), false, "Y"},
{filepath.Join(sysModuleDir, "kvm_intel/parameters/nested"), false, "Y"}, {filepath.Join(sysModuleDir, "kvm_intel/parameters/nested"), false, "Y"},
} }
} else if cpuType == cpuTypeAMD {
cpuData = []testCPUData{
{archAuthenticAMD, "lm svm sse4_1", false},
}
moduleData = []testModuleData{
{filepath.Join(sysModuleDir, "kvm_amd/parameters/nested"), false, "1"},
}
}
devNull, err := os.OpenFile(os.DevNull, os.O_WRONLY, 0666) devNull, err := os.OpenFile(os.DevNull, os.O_WRONLY, 0666)
assert.NoError(err) assert.NoError(err)
@ -175,7 +188,7 @@ func TestCheckCheckKernelModulesNoNesting(t *testing.T) {
{filepath.Join(sysModuleDir, "kvm_intel/parameters/nested"), false, "N"}, {filepath.Join(sysModuleDir, "kvm_intel/parameters/nested"), false, "N"},
} }
vendor := "GenuineIntel" vendor := archGenuineIntel
flags := "vmx lm sse4_1 hypervisor" flags := "vmx lm sse4_1 hypervisor"
_, err = checkKernelModules(requiredModules, archKernelParamHandler) _, err = checkKernelModules(requiredModules, archKernelParamHandler)
@ -259,7 +272,7 @@ func TestCheckCheckKernelModulesNoUnrestrictedGuest(t *testing.T) {
{filepath.Join(sysModuleDir, "kvm_intel/parameters/unrestricted_guest"), false, "N"}, {filepath.Join(sysModuleDir, "kvm_intel/parameters/unrestricted_guest"), false, "N"},
} }
vendor := "GenuineIntel" vendor := archGenuineIntel
flags := "vmx lm sse4_1" flags := "vmx lm sse4_1"
_, err = checkKernelModules(requiredModules, archKernelParamHandler) _, err = checkKernelModules(requiredModules, archKernelParamHandler)
@ -334,21 +347,41 @@ func TestCheckHostIsVMContainerCapable(t *testing.T) {
t.Fatal(err) t.Fatal(err)
} }
cpuData := []testCPUData{ var cpuData []testCPUData
var moduleData []testModuleData
if cpuType == cpuTypeIntel {
cpuData = []testCPUData{
{"", "", true}, {"", "", true},
{"Intel", "", true}, {"Intel", "", true},
{"GenuineIntel", "", true}, {archGenuineIntel, "", true},
{"GenuineIntel", "lm", true}, {archGenuineIntel, "lm", true},
{"GenuineIntel", "lm vmx", true}, {archGenuineIntel, "lm vmx", true},
{"GenuineIntel", "lm vmx sse4_1", false}, {archGenuineIntel, "lm vmx sse4_1", false},
} }
moduleData := []testModuleData{ moduleData = []testModuleData{
{filepath.Join(sysModuleDir, "kvm"), true, ""}, {filepath.Join(sysModuleDir, "kvm"), true, ""},
{filepath.Join(sysModuleDir, "kvm_intel"), true, ""}, {filepath.Join(sysModuleDir, "kvm_intel"), true, ""},
{filepath.Join(sysModuleDir, "kvm_intel/parameters/nested"), false, "Y"}, {filepath.Join(sysModuleDir, "kvm_intel/parameters/nested"), false, "Y"},
{filepath.Join(sysModuleDir, "kvm_intel/parameters/unrestricted_guest"), false, "Y"}, {filepath.Join(sysModuleDir, "kvm_intel/parameters/unrestricted_guest"), false, "Y"},
} }
} else if cpuType == cpuTypeAMD {
cpuData = []testCPUData{
{"", "", true},
{"AMD", "", true},
{archAuthenticAMD, "", true},
{archAuthenticAMD, "lm", true},
{archAuthenticAMD, "lm svm", true},
{archAuthenticAMD, "lm svm sse4_1", false},
}
moduleData = []testModuleData{
{filepath.Join(sysModuleDir, "kvm"), true, ""},
{filepath.Join(sysModuleDir, "kvm_amd"), true, ""},
{filepath.Join(sysModuleDir, "kvm_amd/parameters/nested"), false, "1"},
}
}
setupCheckHostIsVMContainerCapable(assert, cpuInfoFile, cpuData, moduleData) setupCheckHostIsVMContainerCapable(assert, cpuInfoFile, cpuData, moduleData)

View File

@ -40,6 +40,9 @@ var archRequiredKernelModules = map[string]kernelModule{
}, },
} }
func setCPUtype() {
}
// 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 {

View File

@ -44,6 +44,9 @@ var archRequiredKernelModules = map[string]kernelModule{
}, },
} }
func setCPUtype() {
}
func archHostCanCreateVMContainer() error { func archHostCanCreateVMContainer() error {
return kvmIsUsable() return kvmIsUsable()
} }