github.com/alibaba/sealer@v0.8.6-0.20220430115802-37a2bdaa8173/utils/platform/cpu.go (about) 1 // Copyright © 2022 Alibaba Group Holding Ltd. 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 package platform 16 17 import ( 18 "bufio" 19 "os" 20 "runtime" 21 "strings" 22 "sync" 23 24 "github.com/alibaba/sealer/logger" 25 26 "github.com/pkg/errors" 27 ) 28 29 const ( 30 ARM = "arm" 31 ARM64 = "arm64" 32 AMD = "amd64" 33 UNKNOWN = "unknown" 34 WINDOWS = "windows" 35 DARWIN = "darwin" 36 LINUX = "linux" 37 ) 38 39 var ( 40 cpuVariantValue string 41 cpuVariantOnce sync.Once 42 ) 43 44 func cpuVariant() string { 45 cpuVariantOnce.Do(func() { 46 if isArmArch(runtime.GOARCH) { 47 variant, err := getCPUInfo("Cpu architecture") 48 if err != nil { 49 logger.Error(err) 50 } 51 model, err := getCPUInfo("model name") 52 if !strings.Contains(err.Error(), ErrNotFound.Error()) { 53 logger.Error(err) 54 } 55 cpuVariantValue = GetCPUVariantByInfo(runtime.GOOS, runtime.GOARCH, variant, model) 56 } 57 }) 58 return cpuVariantValue 59 } 60 61 // For Linux, We can just parse this information from "/proc/cpuinfo" 62 func getCPUInfo(pattern string) (info string, err error) { 63 if !isLinuxOS(runtime.GOOS) { 64 return "", errors.Wrapf(ErrNotImplemented, "getCPUInfo for OS %s", runtime.GOOS) 65 } 66 67 cpuinfo, err := os.Open("/proc/cpuinfo") 68 if err != nil { 69 return "", err 70 } 71 defer func() { 72 if err := cpuinfo.Close(); err != nil { 73 logger.Error("failed to close file") 74 } 75 }() 76 77 scanner := bufio.NewScanner(cpuinfo) 78 for scanner.Scan() { 79 newline := scanner.Text() 80 list := strings.Split(newline, ":") 81 82 if len(list) > 1 && strings.EqualFold(strings.TrimSpace(list[0]), pattern) { 83 return strings.TrimSpace(list[1]), nil 84 } 85 } 86 87 // Check whether the scanner encountered errors 88 err = scanner.Err() 89 if err != nil { 90 return "", err 91 } 92 93 return "", errors.Wrapf(ErrNotFound, "getCPUInfo for pattern: %s", pattern) 94 } 95 96 // GetCPUVariantByInfo get 'Cpu architecture', 'model name' from /proc/cpuinfo 97 func GetCPUVariantByInfo(os, arch, variant, model string) string { 98 if os == WINDOWS || os == DARWIN { 99 // Windows/Darwin only supports v7 for ARM32 and v8 for ARM64, and so we can use 100 // runtime.GOARCH to determine the variants 101 var variant string 102 switch arch { 103 case ARM64: 104 variant = "v8" 105 case ARM: 106 variant = "v7" 107 default: 108 variant = UNKNOWN 109 } 110 111 return variant 112 } 113 114 if arch == ARM && variant == "7" { 115 if strings.HasPrefix(strings.ToLower(model), "armv6-compatible") { 116 variant = "6" 117 } 118 } 119 120 switch strings.ToLower(variant) { 121 case "8", "aarch64": 122 variant = "v8" 123 case "7", "7m", "?(12)", "?(13)", "?(14)", "?(15)", "?(16)", "?(17)": 124 variant = "v7" 125 case "6", "6tej": 126 variant = "v6" 127 case "5", "5t", "5te", "5tej": 128 variant = "v5" 129 case "4", "4t": 130 variant = "v4" 131 case "3": 132 variant = "v3" 133 default: 134 variant = "unknown" 135 } 136 137 return variant 138 }