github.com/nicocha30/gvisor-ligolo@v0.0.0-20230726075806-989fa2c0a413/pkg/cpuid/features_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 // block is a collection of 32 Feature bits. 21 type block int 22 23 // blockSize is the number of bits in a single block. 24 const blockSize = 32 25 26 // featureID returns the feature identified by the given block and bit. 27 // 28 // Feature bits are numbered according to "blocks". Each block is 32 bits, and 29 // feature bits from the same source (cpuid leaf/level) are in the same block. 30 func featureID(b block, bit int) Feature { 31 return Feature(blockSize*int(b) + bit) 32 } 33 34 // block returns the block associated with the feature. 35 func (f Feature) block() block { 36 return block(f / blockSize) 37 } 38 39 // Bit returns the bit associated with the feature. 40 func (f Feature) bit() uint32 { 41 return uint32(1 << (f % blockSize)) 42 } 43 44 // ChangeableSet is a feature set that can allows changes. 45 type ChangeableSet interface { 46 Query(in In) Out 47 Set(in In, out Out) 48 } 49 50 // Set sets the given feature. 51 func (f Feature) Set(s ChangeableSet) { 52 f.set(s, true) 53 } 54 55 // Unset unsets the given feature. 56 func (f Feature) Unset(s ChangeableSet) { 57 f.set(s, false) 58 } 59 60 // set sets the given feature. 61 func (f Feature) set(s ChangeableSet, on bool) { 62 switch f.block() { 63 case 0: 64 out := s.Query(In{Eax: uint32(featureInfo)}) 65 if on { 66 out.Ecx |= f.bit() 67 } else { 68 out.Ecx &^= f.bit() 69 } 70 s.Set(In{Eax: uint32(featureInfo)}, out) 71 case 1: 72 out := s.Query(In{Eax: uint32(featureInfo)}) 73 if on { 74 out.Edx |= f.bit() 75 } else { 76 out.Edx &^= f.bit() 77 } 78 s.Set(In{Eax: uint32(featureInfo)}, out) 79 case 2: 80 out := s.Query(In{Eax: uint32(extendedFeatureInfo)}) 81 if on { 82 out.Ebx |= f.bit() 83 } else { 84 out.Ebx &^= f.bit() 85 } 86 s.Set(In{Eax: uint32(extendedFeatureInfo)}, out) 87 case 3: 88 out := s.Query(In{Eax: uint32(extendedFeatureInfo)}) 89 if on { 90 out.Ecx |= f.bit() 91 } else { 92 out.Ecx &^= f.bit() 93 } 94 s.Set(In{Eax: uint32(extendedFeatureInfo)}, out) 95 case 4: 96 // Need to turn on the bit in block 0. 97 out := s.Query(In{Eax: uint32(featureInfo)}) 98 out.Ecx |= (1 << 26) 99 s.Set(In{Eax: uint32(featureInfo)}, out) 100 101 out = s.Query(In{Eax: xSaveInfoSub.eax(), Ecx: xSaveInfoSub.ecx()}) 102 if on { 103 out.Eax |= f.bit() 104 } else { 105 out.Eax &^= f.bit() 106 } 107 s.Set(In{Eax: xSaveInfoSub.eax(), Ecx: xSaveInfoSub.ecx()}, out) 108 case 5, 6: 109 // Need to enable extended features. 110 out := s.Query(In{Eax: uint32(extendedFunctionInfo)}) 111 if out.Eax < uint32(extendedFeatures) { 112 out.Eax = uint32(extendedFeatures) 113 } 114 s.Set(In{Eax: uint32(extendedFunctionInfo)}, out) 115 out = s.Query(In{Eax: uint32(extendedFeatures)}) 116 if f.block() == 5 { 117 if on { 118 out.Ecx |= f.bit() 119 } else { 120 out.Ecx &^= f.bit() 121 } 122 } else { 123 if on { 124 out.Edx |= f.bit() 125 } else { 126 out.Edx &^= f.bit() 127 } 128 } 129 s.Set(In{Eax: uint32(extendedFeatures)}, out) 130 } 131 } 132 133 // check checks for the given feature. 134 // 135 //go:nosplit 136 func (f Feature) check(fs FeatureSet) bool { 137 switch f.block() { 138 case 0: 139 _, _, cx, _ := fs.query(featureInfo) 140 return (cx & f.bit()) != 0 141 case 1: 142 _, _, _, dx := fs.query(featureInfo) 143 return (dx & f.bit()) != 0 144 case 2: 145 _, bx, _, _ := fs.query(extendedFeatureInfo) 146 return (bx & f.bit()) != 0 147 case 3: 148 _, _, cx, _ := fs.query(extendedFeatureInfo) 149 return (cx & f.bit()) != 0 150 case 4: 151 // Need to check appropriate bit in block 0. 152 _, _, cx, _ := fs.query(featureInfo) 153 if (cx & (1 << 26)) == 0 { 154 return false 155 } 156 ax, _, _, _ := fs.query(xSaveInfoSub) 157 return (ax & f.bit()) != 0 158 case 5, 6: 159 // eax=0x80000000 gets supported extended levels. We use this 160 // to determine if there are any non-zero block 4 or block 6 161 // bits to find. 162 ax, _, _, _ := fs.query(extendedFunctionInfo) 163 if ax >= uint32(extendedFeatures) { 164 _, _, cx, dx := fs.query(extendedFeatures) 165 if f.block() == 5 { 166 return (cx & f.bit()) != 0 167 } 168 // Ignore features duplicated from block 1 on AMD. 169 // These bits are reserved on Intel. 170 return ((dx &^ block6DuplicateMask) & f.bit()) != 0 171 } 172 return false 173 default: 174 return false 175 } 176 } 177 178 // Block 0 constants are all of the "basic" feature bits returned by a cpuid in 179 // ecx with eax=1. 180 const ( 181 X86FeatureSSE3 Feature = iota 182 X86FeaturePCLMULDQ 183 X86FeatureDTES64 184 X86FeatureMONITOR 185 X86FeatureDSCPL 186 X86FeatureVMX 187 X86FeatureSMX 188 X86FeatureEST 189 X86FeatureTM2 190 X86FeatureSSSE3 // Not a typo, "supplemental" SSE3. 191 X86FeatureCNXTID 192 X86FeatureSDBG 193 X86FeatureFMA 194 X86FeatureCX16 195 X86FeatureXTPR 196 X86FeaturePDCM 197 _ // ecx bit 16 is reserved. 198 X86FeaturePCID 199 X86FeatureDCA 200 X86FeatureSSE4_1 201 X86FeatureSSE4_2 202 X86FeatureX2APIC 203 X86FeatureMOVBE 204 X86FeaturePOPCNT 205 X86FeatureTSCD 206 X86FeatureAES 207 X86FeatureXSAVE 208 X86FeatureOSXSAVE 209 X86FeatureAVX 210 X86FeatureF16C 211 X86FeatureRDRAND 212 X86FeatureHypervisor 213 ) 214 215 // Block 1 constants are all of the "basic" feature bits returned by a cpuid in 216 // edx with eax=1. 217 const ( 218 X86FeatureFPU Feature = 32 + iota 219 X86FeatureVME 220 X86FeatureDE 221 X86FeaturePSE 222 X86FeatureTSC 223 X86FeatureMSR 224 X86FeaturePAE 225 X86FeatureMCE 226 X86FeatureCX8 227 X86FeatureAPIC 228 _ // edx bit 10 is reserved. 229 X86FeatureSEP 230 X86FeatureMTRR 231 X86FeaturePGE 232 X86FeatureMCA 233 X86FeatureCMOV 234 X86FeaturePAT 235 X86FeaturePSE36 236 X86FeaturePSN 237 X86FeatureCLFSH 238 _ // edx bit 20 is reserved. 239 X86FeatureDS 240 X86FeatureACPI 241 X86FeatureMMX 242 X86FeatureFXSR 243 X86FeatureSSE 244 X86FeatureSSE2 245 X86FeatureSS 246 X86FeatureHTT 247 X86FeatureTM 248 X86FeatureIA64 249 X86FeaturePBE 250 ) 251 252 // Block 2 bits are the "structured extended" features returned in ebx for 253 // eax=7, ecx=0. 254 const ( 255 X86FeatureFSGSBase Feature = 2*32 + iota 256 X86FeatureTSC_ADJUST 257 _ // ebx bit 2 is reserved. 258 X86FeatureBMI1 259 X86FeatureHLE 260 X86FeatureAVX2 261 X86FeatureFDP_EXCPTN_ONLY 262 X86FeatureSMEP 263 X86FeatureBMI2 264 X86FeatureERMS 265 X86FeatureINVPCID 266 X86FeatureRTM 267 X86FeatureCQM 268 X86FeatureFPCSDS 269 X86FeatureMPX 270 X86FeatureRDT 271 X86FeatureAVX512F 272 X86FeatureAVX512DQ 273 X86FeatureRDSEED 274 X86FeatureADX 275 X86FeatureSMAP 276 X86FeatureAVX512IFMA 277 X86FeaturePCOMMIT 278 X86FeatureCLFLUSHOPT 279 X86FeatureCLWB 280 X86FeatureIPT // Intel processor trace. 281 X86FeatureAVX512PF 282 X86FeatureAVX512ER 283 X86FeatureAVX512CD 284 X86FeatureSHA 285 X86FeatureAVX512BW 286 X86FeatureAVX512VL 287 ) 288 289 // Block 3 bits are the "extended" features returned in ecx for eax=7, ecx=0. 290 const ( 291 X86FeaturePREFETCHWT1 Feature = 3*32 + iota 292 X86FeatureAVX512VBMI 293 X86FeatureUMIP 294 X86FeaturePKU 295 X86FeatureOSPKE 296 X86FeatureWAITPKG 297 X86FeatureAVX512_VBMI2 298 X86FeatureCET_SS 299 X86FeatureGFNI 300 X86FeatureVAES 301 X86FeatureVPCLMULQDQ 302 X86FeatureAVX512_VNNI 303 X86FeatureAVX512_BITALG 304 X86FeatureTME 305 X86FeatureAVX512_VPOPCNTDQ 306 _ // ecx bit 15 is reserved 307 X86FeatureLA57 308 // ecx bits 17-21 are reserved 309 _ 310 _ 311 _ 312 _ 313 _ 314 X86FeatureRDPID 315 // ecx bits 23-24 are reserved 316 _ 317 _ 318 X86FeatureCLDEMOTE 319 _ // ecx bit 26 is reserved 320 X86FeatureMOVDIRI 321 X86FeatureMOVDIR64B 322 ) 323 324 // Block 4 constants are for xsave capabilities in CPUID.(EAX=0DH,ECX=01H):EAX. 325 // The CPUID leaf is available only if 'X86FeatureXSAVE' is present. 326 const ( 327 X86FeatureXSAVEOPT Feature = 4*32 + iota 328 X86FeatureXSAVEC 329 X86FeatureXGETBV1 330 X86FeatureXSAVES 331 // EAX[31:4] are reserved. 332 ) 333 334 // Block 5 constants are the extended feature bits in 335 // CPUID.(EAX=0x80000001):ECX. 336 const ( 337 X86FeatureLAHF64 Feature = 5*32 + iota 338 X86FeatureCMP_LEGACY 339 X86FeatureSVM 340 X86FeatureEXTAPIC 341 X86FeatureCR8_LEGACY 342 X86FeatureLZCNT 343 X86FeatureSSE4A 344 X86FeatureMISALIGNSSE 345 X86FeaturePREFETCHW 346 X86FeatureOSVW 347 X86FeatureIBS 348 X86FeatureXOP 349 X86FeatureSKINIT 350 X86FeatureWDT 351 _ // ecx bit 14 is reserved. 352 X86FeatureLWP 353 X86FeatureFMA4 354 X86FeatureTCE 355 _ // ecx bit 18 is reserved. 356 _ // ecx bit 19 is reserved. 357 _ // ecx bit 20 is reserved. 358 X86FeatureTBM 359 X86FeatureTOPOLOGY 360 X86FeaturePERFCTR_CORE 361 X86FeaturePERFCTR_NB 362 _ // ecx bit 25 is reserved. 363 X86FeatureBPEXT 364 X86FeaturePERFCTR_TSC 365 X86FeaturePERFCTR_LLC 366 X86FeatureMWAITX 367 X86FeatureADMSKEXTN 368 _ // ecx bit 31 is reserved. 369 ) 370 371 // Block 6 constants are the extended feature bits in 372 // CPUID.(EAX=0x80000001):EDX. 373 // 374 // These are sparse, and so the bit positions are assigned manually. 375 const ( 376 // On AMD, EDX[24:23] | EDX[17:12] | EDX[9:0] are duplicate features 377 // also defined in block 1 (in identical bit positions). Those features 378 // are not listed here. 379 block6DuplicateMask = 0x183f3ff 380 381 X86FeatureSYSCALL Feature = 6*32 + 11 382 X86FeatureNX Feature = 6*32 + 20 383 X86FeatureMMXEXT Feature = 6*32 + 22 384 X86FeatureFXSR_OPT Feature = 6*32 + 25 385 X86FeatureGBPAGES Feature = 6*32 + 26 386 X86FeatureRDTSCP Feature = 6*32 + 27 387 X86FeatureLM Feature = 6*32 + 29 388 X86Feature3DNOWEXT Feature = 6*32 + 30 389 X86Feature3DNOW Feature = 6*32 + 31 390 ) 391 392 // These are the extended floating point state features. They are used to 393 // enumerate floating point features in XCR0, XSTATE_BV, etc. 394 const ( 395 XSAVEFeatureX87 = 1 << 0 396 XSAVEFeatureSSE = 1 << 1 397 XSAVEFeatureAVX = 1 << 2 398 XSAVEFeatureBNDREGS = 1 << 3 399 XSAVEFeatureBNDCSR = 1 << 4 400 XSAVEFeatureAVX512op = 1 << 5 401 XSAVEFeatureAVX512zmm0 = 1 << 6 402 XSAVEFeatureAVX512zmm16 = 1 << 7 403 XSAVEFeaturePKRU = 1 << 9 404 ) 405 406 // allFeatures is the set of allFeatures. 407 // 408 // These match names used in arch/x86/kernel/cpu/capflags.c. 409 var allFeatures = map[Feature]allFeatureInfo{ 410 // Block 0. 411 X86FeatureSSE3: {"pni", true}, 412 X86FeaturePCLMULDQ: {"pclmulqdq", true}, 413 X86FeatureDTES64: {"dtes64", true}, 414 X86FeatureMONITOR: {"monitor", true}, 415 X86FeatureDSCPL: {"ds_cpl", true}, 416 X86FeatureVMX: {"vmx", true}, 417 X86FeatureSMX: {"smx", true}, 418 X86FeatureEST: {"est", true}, 419 X86FeatureTM2: {"tm2", true}, 420 X86FeatureSSSE3: {"ssse3", true}, 421 X86FeatureCNXTID: {"cid", true}, 422 X86FeatureSDBG: {"sdbg", true}, 423 X86FeatureFMA: {"fma", true}, 424 X86FeatureCX16: {"cx16", true}, 425 X86FeatureXTPR: {"xtpr", true}, 426 X86FeaturePDCM: {"pdcm", true}, 427 X86FeaturePCID: {"pcid", true}, 428 X86FeatureDCA: {"dca", true}, 429 X86FeatureSSE4_1: {"sse4_1", true}, 430 X86FeatureSSE4_2: {"sse4_2", true}, 431 X86FeatureX2APIC: {"x2apic", true}, 432 X86FeatureMOVBE: {"movbe", true}, 433 X86FeaturePOPCNT: {"popcnt", true}, 434 X86FeatureTSCD: {"tsc_deadline_timer", true}, 435 X86FeatureAES: {"aes", true}, 436 X86FeatureXSAVE: {"xsave", true}, 437 X86FeatureAVX: {"avx", true}, 438 X86FeatureF16C: {"f16c", true}, 439 X86FeatureRDRAND: {"rdrand", true}, 440 X86FeatureHypervisor: {"hypervisor", true}, 441 X86FeatureOSXSAVE: {"osxsave", false}, 442 443 // Block 1. 444 X86FeatureFPU: {"fpu", true}, 445 X86FeatureVME: {"vme", true}, 446 X86FeatureDE: {"de", true}, 447 X86FeaturePSE: {"pse", true}, 448 X86FeatureTSC: {"tsc", true}, 449 X86FeatureMSR: {"msr", true}, 450 X86FeaturePAE: {"pae", true}, 451 X86FeatureMCE: {"mce", true}, 452 X86FeatureCX8: {"cx8", true}, 453 X86FeatureAPIC: {"apic", true}, 454 X86FeatureSEP: {"sep", true}, 455 X86FeatureMTRR: {"mtrr", true}, 456 X86FeaturePGE: {"pge", true}, 457 X86FeatureMCA: {"mca", true}, 458 X86FeatureCMOV: {"cmov", true}, 459 X86FeaturePAT: {"pat", true}, 460 X86FeaturePSE36: {"pse36", true}, 461 X86FeaturePSN: {"pn", true}, 462 X86FeatureCLFSH: {"clflush", true}, 463 X86FeatureDS: {"dts", true}, 464 X86FeatureACPI: {"acpi", true}, 465 X86FeatureMMX: {"mmx", true}, 466 X86FeatureFXSR: {"fxsr", true}, 467 X86FeatureSSE: {"sse", true}, 468 X86FeatureSSE2: {"sse2", true}, 469 X86FeatureSS: {"ss", true}, 470 X86FeatureHTT: {"ht", true}, 471 X86FeatureTM: {"tm", true}, 472 X86FeatureIA64: {"ia64", true}, 473 X86FeaturePBE: {"pbe", true}, 474 475 // Block 2. 476 X86FeatureFSGSBase: {"fsgsbase", true}, 477 X86FeatureTSC_ADJUST: {"tsc_adjust", true}, 478 X86FeatureBMI1: {"bmi1", true}, 479 X86FeatureHLE: {"hle", true}, 480 X86FeatureAVX2: {"avx2", true}, 481 X86FeatureSMEP: {"smep", true}, 482 X86FeatureBMI2: {"bmi2", true}, 483 X86FeatureERMS: {"erms", true}, 484 X86FeatureINVPCID: {"invpcid", true}, 485 X86FeatureRTM: {"rtm", true}, 486 X86FeatureCQM: {"cqm", true}, 487 X86FeatureMPX: {"mpx", true}, 488 X86FeatureRDT: {"rdt_a", true}, 489 X86FeatureAVX512F: {"avx512f", true}, 490 X86FeatureAVX512DQ: {"avx512dq", true}, 491 X86FeatureRDSEED: {"rdseed", true}, 492 X86FeatureADX: {"adx", true}, 493 X86FeatureSMAP: {"smap", true}, 494 X86FeatureCLWB: {"clwb", true}, 495 X86FeatureAVX512PF: {"avx512pf", true}, 496 X86FeatureAVX512ER: {"avx512er", true}, 497 X86FeatureAVX512CD: {"avx512cd", true}, 498 X86FeatureSHA: {"sha_ni", true}, 499 X86FeatureAVX512BW: {"avx512bw", true}, 500 X86FeatureAVX512VL: {"avx512vl", true}, 501 X86FeatureFDP_EXCPTN_ONLY: {"fdp_excptn_only", false}, 502 X86FeatureFPCSDS: {"fpcsds", false}, 503 X86FeatureIPT: {"ipt", false}, 504 X86FeatureCLFLUSHOPT: {"clfushopt", false}, 505 506 // Block 3. 507 X86FeatureAVX512VBMI: {"avx512vbmi", true}, 508 X86FeatureUMIP: {"umip", true}, 509 X86FeaturePKU: {"pku", true}, 510 X86FeatureOSPKE: {"ospke", true}, 511 X86FeatureWAITPKG: {"waitpkg", true}, 512 X86FeatureAVX512_VBMI2: {"avx512_vbmi2", true}, 513 X86FeatureGFNI: {"gfni", true}, 514 X86FeatureCET_SS: {"cet_ss", false}, 515 X86FeatureVAES: {"vaes", true}, 516 X86FeatureVPCLMULQDQ: {"vpclmulqdq", true}, 517 X86FeatureAVX512_VNNI: {"avx512_vnni", true}, 518 X86FeatureAVX512_BITALG: {"avx512_bitalg", true}, 519 X86FeatureTME: {"tme", true}, 520 X86FeatureAVX512_VPOPCNTDQ: {"avx512_vpopcntdq", true}, 521 X86FeatureLA57: {"la57", true}, 522 X86FeatureRDPID: {"rdpid", true}, 523 X86FeatureCLDEMOTE: {"cldemote", true}, 524 X86FeatureMOVDIRI: {"movdiri", true}, 525 X86FeatureMOVDIR64B: {"movdir64b", true}, 526 X86FeaturePREFETCHWT1: {"prefetchwt1", false}, 527 528 // Block 4. 529 X86FeatureXSAVEOPT: {"xsaveopt", true}, 530 X86FeatureXSAVEC: {"xsavec", true}, 531 X86FeatureXGETBV1: {"xgetbv1", true}, 532 X86FeatureXSAVES: {"xsaves", true}, 533 534 // Block 5. 535 X86FeatureLAHF64: {"lahf_lm", true}, // LAHF/SAHF in long mode. 536 X86FeatureCMP_LEGACY: {"cmp_legacy", true}, 537 X86FeatureSVM: {"svm", true}, 538 X86FeatureEXTAPIC: {"extapic", true}, 539 X86FeatureCR8_LEGACY: {"cr8_legacy", true}, 540 X86FeatureLZCNT: {"abm", true}, // Advanced bit manipulation. 541 X86FeatureSSE4A: {"sse4a", true}, 542 X86FeatureMISALIGNSSE: {"misalignsse", true}, 543 X86FeaturePREFETCHW: {"3dnowprefetch", true}, 544 X86FeatureOSVW: {"osvw", true}, 545 X86FeatureIBS: {"ibs", true}, 546 X86FeatureXOP: {"xop", true}, 547 X86FeatureSKINIT: {"skinit", true}, 548 X86FeatureWDT: {"wdt", true}, 549 X86FeatureLWP: {"lwp", true}, 550 X86FeatureFMA4: {"fma4", true}, 551 X86FeatureTCE: {"tce", true}, 552 X86FeatureTBM: {"tbm", true}, 553 X86FeatureTOPOLOGY: {"topoext", true}, 554 X86FeaturePERFCTR_CORE: {"perfctr_core", true}, 555 X86FeaturePERFCTR_NB: {"perfctr_nb", true}, 556 X86FeatureBPEXT: {"bpext", true}, 557 X86FeaturePERFCTR_TSC: {"ptsc", true}, 558 X86FeaturePERFCTR_LLC: {"perfctr_llc", true}, 559 X86FeatureMWAITX: {"mwaitx", true}, 560 X86FeatureADMSKEXTN: {"ad_mask_extn", false}, 561 562 // Block 6. 563 X86FeatureSYSCALL: {"syscall", true}, 564 X86FeatureNX: {"nx", true}, 565 X86FeatureMMXEXT: {"mmxext", true}, 566 X86FeatureFXSR_OPT: {"fxsr_opt", true}, 567 X86FeatureGBPAGES: {"pdpe1gb", true}, 568 X86FeatureRDTSCP: {"rdtscp", true}, 569 X86FeatureLM: {"lm", true}, 570 X86Feature3DNOWEXT: {"3dnowext", true}, 571 X86Feature3DNOW: {"3dnow", true}, 572 } 573 574 // linuxBlockOrder defines the order in which linux organizes the feature 575 // blocks. Linux also tracks feature bits in 32-bit blocks, but in an order 576 // which doesn't match well here, so for the /proc/cpuinfo generation we simply 577 // re-map the blocks to Linux's ordering and then go through the bits in each 578 // block. 579 var linuxBlockOrder = []block{1, 6, 0, 5, 2, 4, 3} 580 581 func archFlagOrder(fn func(Feature)) { 582 for _, b := range linuxBlockOrder { 583 for i := 0; i < blockSize; i++ { 584 f := featureID(b, i) 585 if _, ok := allFeatures[f]; ok { 586 fn(f) 587 } 588 } 589 } 590 }