diff --git a/cli/kata-check.go b/cli/kata-check.go index 89c59d33d9..7b13892540 100644 --- a/cli/kata-check.go +++ b/cli/kata-check.go @@ -283,6 +283,8 @@ var kataCheckCLICommand = cli.Command{ Usage: "tests if system can run " + project, Action: func(context *cli.Context) error { + setCPUtype() + details := vmContainerCapableDetails{ cpuInfoFile: procCPUInfo, requiredCPUFlags: archRequiredCPUFlags, diff --git a/cli/kata-check_amd64.go b/cli/kata-check_amd64.go index a642602059..d3b6076ae3 100644 --- a/cli/kata-check_amd64.go +++ b/cli/kata-check_amd64.go @@ -7,52 +7,124 @@ package main import ( "github.com/sirupsen/logrus" + "io/ioutil" + "strings" ) const ( cpuFlagsTag = genericCPUFlagsTag archCPUVendorField = genericCPUVendorField 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 // human-readable description of that value. -var archRequiredCPUFlags = map[string]string{ - "vmx": "Virtualization support", - "lm": "64Bit CPU", - "sse4_1": "SSE4.1", -} +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{ - "GenuineIntel": "Intel Architecture CPU", -} +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_intel": { - desc: "Intel KVM", - parameters: map[string]string{ - "nested": "Y", - // "VMX Unrestricted mode support". This is used - // as a heuristic to determine if the system is - // "new enough" to run a Kata Container - // (atleast a Westmere). - "unrestricted_guest": "Y", - }, - }, - "vhost": { - desc: "Host kernel accelerator for virtio", - }, - "vhost_net": { - desc: "Host kernel accelerator for virtio network", - }, +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": { + desc: msgKernelVM, + }, + "kvm_intel": { + desc: "Intel KVM", + parameters: map[string]string{ + "nested": "Y", + // "VMX Unrestricted mode support". This is used + // as a heuristic to determine if the system is + // "new enough" to run a Kata Container + // (atleast a Westmere). + "unrestricted_guest": "Y", + }, + }, + "vhost": { + desc: msgKernelVirtio, + }, + "vhost_net": { + 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 diff --git a/cli/kata-check_amd64_test.go b/cli/kata-check_amd64_test.go index 1d28e44937..f8c39784ca 100644 --- a/cli/kata-check_amd64_test.go +++ b/cli/kata-check_amd64_test.go @@ -73,13 +73,26 @@ func TestCCCheckCLIFunction(t *testing.T) { t.Fatal(err) } - cpuData := []testCPUData{ - {"GenuineIntel", "lm vmx sse4_1", false}, - } + var cpuData []testCPUData + var moduleData []testModuleData - moduleData := []testModuleData{ - {filepath.Join(sysModuleDir, "kvm_intel/parameters/unrestricted_guest"), false, "Y"}, - {filepath.Join(sysModuleDir, "kvm_intel/parameters/nested"), false, "Y"}, + if cpuType == cpuTypeIntel { + cpuData = []testCPUData{ + {archGenuineIntel, "lm vmx sse4_1", false}, + } + + moduleData = []testModuleData{ + {filepath.Join(sysModuleDir, "kvm_intel/parameters/unrestricted_guest"), 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) @@ -175,7 +188,7 @@ func TestCheckCheckKernelModulesNoNesting(t *testing.T) { {filepath.Join(sysModuleDir, "kvm_intel/parameters/nested"), false, "N"}, } - vendor := "GenuineIntel" + vendor := archGenuineIntel flags := "vmx lm sse4_1 hypervisor" _, err = checkKernelModules(requiredModules, archKernelParamHandler) @@ -259,7 +272,7 @@ func TestCheckCheckKernelModulesNoUnrestrictedGuest(t *testing.T) { {filepath.Join(sysModuleDir, "kvm_intel/parameters/unrestricted_guest"), false, "N"}, } - vendor := "GenuineIntel" + vendor := archGenuineIntel flags := "vmx lm sse4_1" _, err = checkKernelModules(requiredModules, archKernelParamHandler) @@ -334,20 +347,40 @@ func TestCheckHostIsVMContainerCapable(t *testing.T) { t.Fatal(err) } - cpuData := []testCPUData{ - {"", "", true}, - {"Intel", "", true}, - {"GenuineIntel", "", true}, - {"GenuineIntel", "lm", true}, - {"GenuineIntel", "lm vmx", true}, - {"GenuineIntel", "lm vmx sse4_1", false}, - } + var cpuData []testCPUData + var moduleData []testModuleData - moduleData := []testModuleData{ - {filepath.Join(sysModuleDir, "kvm"), true, ""}, - {filepath.Join(sysModuleDir, "kvm_intel"), true, ""}, - {filepath.Join(sysModuleDir, "kvm_intel/parameters/nested"), false, "Y"}, - {filepath.Join(sysModuleDir, "kvm_intel/parameters/unrestricted_guest"), false, "Y"}, + if cpuType == cpuTypeIntel { + cpuData = []testCPUData{ + {"", "", true}, + {"Intel", "", true}, + {archGenuineIntel, "", true}, + {archGenuineIntel, "lm", true}, + {archGenuineIntel, "lm vmx", true}, + {archGenuineIntel, "lm vmx sse4_1", false}, + } + + moduleData = []testModuleData{ + {filepath.Join(sysModuleDir, "kvm"), true, ""}, + {filepath.Join(sysModuleDir, "kvm_intel"), true, ""}, + {filepath.Join(sysModuleDir, "kvm_intel/parameters/nested"), 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) diff --git a/cli/kata-check_arm64.go b/cli/kata-check_arm64.go index 97af7d433a..20c24c4f4f 100644 --- a/cli/kata-check_arm64.go +++ b/cli/kata-check_arm64.go @@ -40,6 +40,9 @@ var archRequiredKernelModules = map[string]kernelModule{ }, } +func setCPUtype() { +} + // 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 { diff --git a/cli/kata-check_ppc64le.go b/cli/kata-check_ppc64le.go index 9843df0d37..627a7e9dde 100644 --- a/cli/kata-check_ppc64le.go +++ b/cli/kata-check_ppc64le.go @@ -44,6 +44,9 @@ var archRequiredKernelModules = map[string]kernelModule{ }, } +func setCPUtype() { +} + func archHostCanCreateVMContainer() error { return kvmIsUsable() }