github.com/nicocha30/gvisor-ligolo@v0.0.0-20230726075806-989fa2c0a413/pkg/cpuid/native_amd64.go (about) 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 amd64 16 // +build amd64 17 18 package cpuid 19 20 import ( 21 "io/ioutil" 22 "strconv" 23 "strings" 24 25 "github.com/nicocha30/gvisor-ligolo/pkg/log" 26 ) 27 28 // cpuididFunction is a useful type wrapper. The format is eax | (ecx << 32). 29 type cpuidFunction uint64 30 31 func (f cpuidFunction) eax() uint32 { 32 return uint32(f) 33 } 34 35 func (f cpuidFunction) ecx() uint32 { 36 return uint32(f >> 32) 37 } 38 39 // The constants below are the lower or "standard" cpuid functions, ordered as 40 // defined by the hardware. Note that these may not be included in the standard 41 // set of functions that we are allowed to execute, which are filtered in the 42 // Native.Query function defined below. 43 const ( 44 vendorID cpuidFunction = 0x0 // Returns vendor ID and largest standard function. 45 featureInfo cpuidFunction = 0x1 // Returns basic feature bits and processor signature. 46 intelCacheDescriptors cpuidFunction = 0x2 // Returns list of cache descriptors. Intel only. 47 intelSerialNumber cpuidFunction = 0x3 // Returns processor serial number (obsolete on new hardware). Intel only. 48 intelDeterministicCacheParams cpuidFunction = 0x4 // Returns deterministic cache information. Intel only. 49 monitorMwaitParams cpuidFunction = 0x5 // Returns information about monitor/mwait instructions. 50 powerParams cpuidFunction = 0x6 // Returns information about power management and thermal sensors. 51 extendedFeatureInfo cpuidFunction = 0x7 // Returns extended feature bits. 52 _ // Function 0x8 is reserved. 53 intelDCAParams cpuidFunction = 0x9 // Returns direct cache access information. Intel only. 54 intelPMCInfo cpuidFunction = 0xa // Returns information about performance monitoring features. Intel only. 55 intelX2APICInfo cpuidFunction = 0xb // Returns core/logical processor topology. Intel only. 56 _ // Function 0xc is reserved. 57 xSaveInfo cpuidFunction = 0xd // Returns information about extended state management. 58 xSaveInfoSub cpuidFunction = 0xd | (0x1 << 32) // Returns information about extended state management (Sub-leaf). 59 ) 60 61 const xSaveInfoNumLeaves = 64 // Maximum number of xSaveInfo leaves. 62 63 // The "extended" functions. 64 const ( 65 extendedStart cpuidFunction = 0x80000000 66 extendedFunctionInfo cpuidFunction = extendedStart + 0 // Returns highest available extended function in eax. 67 extendedFeatures = extendedStart + 1 // Returns some extended feature bits in edx and ecx. 68 processorBrandString2 = extendedStart + 2 // Processor Name String Identifier. 69 processorBrandString3 = extendedStart + 3 // Processor Name String Identifier. 70 processorBrandString4 = extendedStart + 4 // Processor Name String Identifier. 71 l1CacheAndTLBInfo = extendedStart + 5 // Returns L2 cache information. 72 l2CacheInfo = extendedStart + 6 // Returns L2 cache information. 73 addressSizes = extendedStart + 8 // Physical and virtual address sizes. 74 ) 75 76 var allowedBasicFunctions = [...]bool{ 77 vendorID: true, 78 featureInfo: true, 79 extendedFeatureInfo: true, 80 intelCacheDescriptors: true, 81 intelDeterministicCacheParams: true, 82 xSaveInfo: true, 83 } 84 85 var allowedExtendedFunctions = [...]bool{ 86 extendedFunctionInfo - extendedStart: true, 87 extendedFeatures - extendedStart: true, 88 addressSizes - extendedStart: true, 89 processorBrandString2 - extendedStart: true, 90 processorBrandString3 - extendedStart: true, 91 processorBrandString4 - extendedStart: true, 92 l1CacheAndTLBInfo - extendedStart: true, 93 l2CacheInfo - extendedStart: true, 94 } 95 96 // Function executes a CPUID function. 97 // 98 // This is typically the native function or a Static definition. 99 type Function interface { 100 Query(In) Out 101 } 102 103 // Native is a native Function. 104 // 105 // This implements Function. 106 type Native struct{} 107 108 // In is input to the Query function. 109 // 110 // +stateify savable 111 type In struct { 112 Eax uint32 113 Ecx uint32 114 } 115 116 // normalize drops irrelevant Ecx values. 117 func (i *In) normalize() { 118 switch cpuidFunction(i.Eax) { 119 case vendorID, featureInfo, intelCacheDescriptors, extendedFunctionInfo, extendedFeatures: 120 i.Ecx = 0 // Ignore. 121 case processorBrandString2, processorBrandString3, processorBrandString4, l1CacheAndTLBInfo, l2CacheInfo: 122 i.Ecx = 0 // Ignore. 123 case intelDeterministicCacheParams, extendedFeatureInfo: 124 // Preserve i.Ecx. 125 } 126 } 127 128 // Out is output from the Query function. 129 // 130 // +stateify savable 131 type Out struct { 132 Eax uint32 133 Ebx uint32 134 Ecx uint32 135 Edx uint32 136 } 137 138 // native is the native Query function. 139 func native(In) Out 140 141 // Query executes CPUID natively. 142 // 143 // This implements Function. 144 // 145 //go:nosplit 146 func (*Native) Query(in In) Out { 147 if int(in.Eax) < len(allowedBasicFunctions) && allowedBasicFunctions[in.Eax] { 148 return native(in) 149 } else if in.Eax >= uint32(extendedStart) { 150 if l := int(in.Eax - uint32(extendedStart)); l < len(allowedExtendedFunctions) && allowedExtendedFunctions[l] { 151 return native(in) 152 } 153 } 154 return Out{} // All zeros. 155 } 156 157 // query is a internal wrapper. 158 // 159 //go:nosplit 160 func (fs FeatureSet) query(fn cpuidFunction) (uint32, uint32, uint32, uint32) { 161 out := fs.Query(In{Eax: fn.eax(), Ecx: fn.ecx()}) 162 return out.Eax, out.Ebx, out.Ecx, out.Edx 163 } 164 165 var hostFeatureSet FeatureSet 166 167 // HostFeatureSet returns a host CPUID. 168 // 169 //go:nosplit 170 func HostFeatureSet() FeatureSet { 171 return hostFeatureSet 172 } 173 174 var ( 175 // cpuFreqMHz is the native CPU frequency. 176 cpuFreqMHz float64 177 ) 178 179 // Reads max cpu frequency from host /proc/cpuinfo. Must run before syscall 180 // filter installation. This value is used to create the fake /proc/cpuinfo 181 // from a FeatureSet. 182 func readMaxCPUFreq() { 183 cpuinfob, err := ioutil.ReadFile("/proc/cpuinfo") 184 if err != nil { 185 // Leave it as 0... the VDSO bails out in the same way. 186 log.Warningf("Could not read /proc/cpuinfo: %v", err) 187 return 188 } 189 cpuinfo := string(cpuinfob) 190 191 // We get the value straight from host /proc/cpuinfo. On machines with 192 // frequency scaling enabled, this will only get the current value 193 // which will likely be inaccurate. This is fine on machines with 194 // frequency scaling disabled. 195 for _, line := range strings.Split(cpuinfo, "\n") { 196 if strings.Contains(line, "cpu MHz") { 197 splitMHz := strings.Split(line, ":") 198 if len(splitMHz) < 2 { 199 log.Warningf("Could not read /proc/cpuinfo: malformed cpu MHz line") 200 return 201 } 202 203 // If there was a problem, leave cpuFreqMHz as 0. 204 var err error 205 cpuFreqMHz, err = strconv.ParseFloat(strings.TrimSpace(splitMHz[1]), 64) 206 if err != nil { 207 log.Warningf("Could not parse cpu MHz value %v: %v", splitMHz[1], err) 208 cpuFreqMHz = 0 209 return 210 } 211 return 212 } 213 } 214 log.Warningf("Could not parse /proc/cpuinfo, it is empty or does not contain cpu MHz") 215 216 } 217 218 // archInitialize initializes hostFeatureSet. 219 func archInitialize() { 220 hostFeatureSet = FeatureSet{ 221 Function: &Native{}, 222 }.Fixed() 223 224 readMaxCPUFreq() 225 initHWCap() 226 }