1 // Copyright 2019 The gVisor Authors.
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 //go:build arm64
16 // +build arm64
17 18 package cpuid
19 20 import (
21 "os"
22 "runtime"
23 "strconv"
24 "strings"
25 26 "gvisor.dev/gvisor/pkg/log"
27 )
28 29 // hostFeatureSet is initialized at startup.
30 //
31 // This is copied for HostFeatureSet, below.
32 var hostFeatureSet FeatureSet
33 34 // HostFeatureSet returns a copy of the host FeatureSet.
35 func HostFeatureSet() FeatureSet {
36 return hostFeatureSet
37 }
38 39 // Fixed returns the same feature set.
40 func (fs FeatureSet) Fixed() FeatureSet {
41 return fs
42 }
43 44 // Reads CPU information from host /proc/cpuinfo.
45 //
46 // Must run before syscall filter installation. This value is used to create
47 // the fake /proc/cpuinfo from a FeatureSet.
48 func initCPUInfo() {
49 if runtime.GOOS != "linux" {
50 // Don't try to read Linux-specific /proc files or
51 // warn about them not existing.
52 return
53 }
54 cpuinfob, err := os.ReadFile("/proc/cpuinfo")
55 if err != nil {
56 // Leave everything at 0, nothing can be done.
57 log.Warningf("Could not read /proc/cpuinfo: %v", err)
58 return
59 }
60 cpuinfo := string(cpuinfob)
61 62 // We get the value straight from host /proc/cpuinfo.
63 for _, line := range strings.Split(cpuinfo, "\n") {
64 switch {
65 case strings.Contains(line, "BogoMIPS"):
66 splitMHz := strings.Split(line, ":")
67 if len(splitMHz) < 2 {
68 log.Warningf("Could not read /proc/cpuinfo: malformed BogoMIPS")
69 break
70 }
71 72 // If there was a problem, leave cpuFreqMHz as 0.
73 var err error
74 hostFeatureSet.cpuFreqMHz, err = strconv.ParseFloat(strings.TrimSpace(splitMHz[1]), 64)
75 if err != nil {
76 hostFeatureSet.cpuFreqMHz = 0.0
77 log.Warningf("Could not parse BogoMIPS value %v: %v", splitMHz[1], err)
78 }
79 case strings.Contains(line, "CPU implementer"):
80 splitImpl := strings.Split(line, ":")
81 if len(splitImpl) < 2 {
82 log.Warningf("Could not read /proc/cpuinfo: malformed CPU implementer")
83 break
84 }
85 86 // If there was a problem, leave cpuImplHex as 0.
87 var err error
88 hostFeatureSet.cpuImplHex, err = strconv.ParseUint(strings.TrimSpace(splitImpl[1]), 0, 64)
89 if err != nil {
90 hostFeatureSet.cpuImplHex = 0
91 log.Warningf("Could not parse CPU implementer value %v: %v", splitImpl[1], err)
92 }
93 case strings.Contains(line, "CPU architecture"):
94 splitArch := strings.Split(line, ":")
95 if len(splitArch) < 2 {
96 log.Warningf("Could not read /proc/cpuinfo: malformed CPU architecture")
97 break
98 }
99 100 // If there was a problem, leave cpuArchDec as 0.
101 var err error
102 hostFeatureSet.cpuArchDec, err = strconv.ParseUint(strings.TrimSpace(splitArch[1]), 0, 64)
103 if err != nil {
104 hostFeatureSet.cpuArchDec = 0
105 log.Warningf("Could not parse CPU architecture value %v: %v", splitArch[1], err)
106 }
107 case strings.Contains(line, "CPU variant"):
108 splitVar := strings.Split(line, ":")
109 if len(splitVar) < 2 {
110 log.Warningf("Could not read /proc/cpuinfo: malformed CPU variant")
111 break
112 }
113 114 // If there was a problem, leave cpuVarHex as 0.
115 var err error
116 hostFeatureSet.cpuVarHex, err = strconv.ParseUint(strings.TrimSpace(splitVar[1]), 0, 64)
117 if err != nil {
118 hostFeatureSet.cpuVarHex = 0
119 log.Warningf("Could not parse CPU variant value %v: %v", splitVar[1], err)
120 }
121 case strings.Contains(line, "CPU part"):
122 splitPart := strings.Split(line, ":")
123 if len(splitPart) < 2 {
124 log.Warningf("Could not read /proc/cpuinfo: malformed CPU part")
125 break
126 }
127 128 // If there was a problem, leave cpuPartHex as 0.
129 var err error
130 hostFeatureSet.cpuPartHex, err = strconv.ParseUint(strings.TrimSpace(splitPart[1]), 0, 64)
131 if err != nil {
132 hostFeatureSet.cpuPartHex = 0
133 log.Warningf("Could not parse CPU part value %v: %v", splitPart[1], err)
134 }
135 case strings.Contains(line, "CPU revision"):
136 splitRev := strings.Split(line, ":")
137 if len(splitRev) < 2 {
138 log.Warningf("Could not read /proc/cpuinfo: malformed CPU revision")
139 break
140 }
141 142 // If there was a problem, leave cpuRevDec as 0.
143 var err error
144 hostFeatureSet.cpuRevDec, err = strconv.ParseUint(strings.TrimSpace(splitRev[1]), 0, 64)
145 if err != nil {
146 hostFeatureSet.cpuRevDec = 0
147 log.Warningf("Could not parse CPU revision value %v: %v", splitRev[1], err)
148 }
149 }
150 }
151 }
152 153 // archInitialize initializes hostFeatureSet.
154 func archInitialize() {
155 initCPUInfo()
156 initHWCap()
157 }
158