github.com/sealerio/sealer@v0.11.1-0.20240507115618-f4f89c5853ae/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/pkg/errors" 25 "github.com/sirupsen/logrus" 26 ) 27 28 const ( 29 ARM = "arm" 30 ARM64 = "arm64" 31 AMD = "amd64" 32 UNKNOWN = "unknown" 33 WINDOWS = "windows" 34 DARWIN = "darwin" 35 LINUX = "linux" 36 ) 37 38 var ( 39 cpuVariantValue string 40 cpuVariantOnce sync.Once 41 ) 42 43 func cpuVariant() string { 44 cpuVariantOnce.Do(func() { 45 if isArmArch(runtime.GOARCH) { 46 variant, err := getCPUInfo("Cpu architecture") 47 if err != nil { 48 logrus.Error(err) 49 } 50 model, err := getCPUInfo("model name") 51 if err != nil && !strings.Contains(err.Error(), ErrNotFound.Error()) { 52 logrus.Error(err) 53 } 54 cpuVariantValue = GetCPUVariantByInfo(runtime.GOOS, runtime.GOARCH, variant, model) 55 } 56 }) 57 return cpuVariantValue 58 } 59 60 // For Linux, We can just parse this information from "/proc/cpuinfo" 61 func getCPUInfo(pattern string) (info string, err error) { 62 if !isLinuxOS(runtime.GOOS) { 63 return "", errors.Wrapf(ErrNotImplemented, "getCPUInfo for OS %s", runtime.GOOS) 64 } 65 66 cpuinfo, err := os.Open("/proc/cpuinfo") 67 if err != nil { 68 return "", err 69 } 70 defer func() { 71 if err := cpuinfo.Close(); err != nil { 72 logrus.Errorf("failed to close file: %v", err) 73 } 74 }() 75 76 scanner := bufio.NewScanner(cpuinfo) 77 for scanner.Scan() { 78 newline := scanner.Text() 79 list := strings.Split(newline, ":") 80 81 if len(list) > 1 && strings.EqualFold(strings.TrimSpace(list[0]), pattern) { 82 return strings.TrimSpace(list[1]), nil 83 } 84 } 85 86 // Check whether the scanner encountered errors 87 err = scanner.Err() 88 if err != nil { 89 return "", err 90 } 91 92 return "", errors.Wrapf(ErrNotFound, "getCPUInfo for pattern: %s", pattern) 93 } 94 95 // GetCPUVariantByInfo get 'Cpu architecture', 'model name' from /proc/cpuinfo 96 func GetCPUVariantByInfo(os, arch, variant, model string) string { 97 if os == WINDOWS || os == DARWIN { 98 // Windows/Darwin only supports v7 for ARM32 and v8 for ARM64, and so we can use 99 // runtime.GOARCH to determine the variants 100 var variant string 101 switch arch { 102 case ARM64: 103 variant = "v8" 104 case ARM: 105 variant = "v7" 106 default: 107 variant = UNKNOWN 108 } 109 110 return variant 111 } 112 113 if arch == ARM && variant == "7" { 114 if strings.HasPrefix(strings.ToLower(model), "armv6-compatible") { 115 variant = "6" 116 } 117 } 118 119 switch strings.ToLower(variant) { 120 case "8", "aarch64": 121 variant = "v8" 122 case "7", "7m", "?(12)", "?(13)", "?(14)", "?(15)", "?(16)", "?(17)": 123 variant = "v7" 124 case "6", "6tej": 125 variant = "v6" 126 case "5", "5t", "5te", "5tej": 127 variant = "v5" 128 case "4", "4t": 129 variant = "v4" 130 case "3": 131 variant = "v3" 132 default: 133 variant = "unknown" 134 } 135 136 return variant 137 }