native_arm64.go raw

   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