123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208 |
- // Copyright (c) 2020 Klaus Post, released under MIT License. See LICENSE file.
- // Copyright 2018 The Go Authors. All rights reserved.
- // Use of this source code is governed by a BSD-style
- // license that can be found in the LICENSE file located
- // here https://github.com/golang/sys/blob/master/LICENSE
- package cpuid
- import (
- "encoding/binary"
- "io/ioutil"
- "runtime"
- )
- // HWCAP bits.
- const (
- hwcap_FP = 1 << 0
- hwcap_ASIMD = 1 << 1
- hwcap_EVTSTRM = 1 << 2
- hwcap_AES = 1 << 3
- hwcap_PMULL = 1 << 4
- hwcap_SHA1 = 1 << 5
- hwcap_SHA2 = 1 << 6
- hwcap_CRC32 = 1 << 7
- hwcap_ATOMICS = 1 << 8
- hwcap_FPHP = 1 << 9
- hwcap_ASIMDHP = 1 << 10
- hwcap_CPUID = 1 << 11
- hwcap_ASIMDRDM = 1 << 12
- hwcap_JSCVT = 1 << 13
- hwcap_FCMA = 1 << 14
- hwcap_LRCPC = 1 << 15
- hwcap_DCPOP = 1 << 16
- hwcap_SHA3 = 1 << 17
- hwcap_SM3 = 1 << 18
- hwcap_SM4 = 1 << 19
- hwcap_ASIMDDP = 1 << 20
- hwcap_SHA512 = 1 << 21
- hwcap_SVE = 1 << 22
- hwcap_ASIMDFHM = 1 << 23
- hwcap_DIT = 1 << 24
- hwcap_USCAT = 1 << 25
- hwcap_ILRCPC = 1 << 26
- hwcap_FLAGM = 1 << 27
- hwcap_SSBS = 1 << 28
- hwcap_SB = 1 << 29
- hwcap_PACA = 1 << 30
- hwcap_PACG = 1 << 31
- hwcap_GCS = 1 << 32
- hwcap2_DCPODP = 1 << 0
- hwcap2_SVE2 = 1 << 1
- hwcap2_SVEAES = 1 << 2
- hwcap2_SVEPMULL = 1 << 3
- hwcap2_SVEBITPERM = 1 << 4
- hwcap2_SVESHA3 = 1 << 5
- hwcap2_SVESM4 = 1 << 6
- hwcap2_FLAGM2 = 1 << 7
- hwcap2_FRINT = 1 << 8
- hwcap2_SVEI8MM = 1 << 9
- hwcap2_SVEF32MM = 1 << 10
- hwcap2_SVEF64MM = 1 << 11
- hwcap2_SVEBF16 = 1 << 12
- hwcap2_I8MM = 1 << 13
- hwcap2_BF16 = 1 << 14
- hwcap2_DGH = 1 << 15
- hwcap2_RNG = 1 << 16
- hwcap2_BTI = 1 << 17
- hwcap2_MTE = 1 << 18
- hwcap2_ECV = 1 << 19
- hwcap2_AFP = 1 << 20
- hwcap2_RPRES = 1 << 21
- hwcap2_MTE3 = 1 << 22
- hwcap2_SME = 1 << 23
- hwcap2_SME_I16I64 = 1 << 24
- hwcap2_SME_F64F64 = 1 << 25
- hwcap2_SME_I8I32 = 1 << 26
- hwcap2_SME_F16F32 = 1 << 27
- hwcap2_SME_B16F32 = 1 << 28
- hwcap2_SME_F32F32 = 1 << 29
- hwcap2_SME_FA64 = 1 << 30
- hwcap2_WFXT = 1 << 31
- hwcap2_EBF16 = 1 << 32
- hwcap2_SVE_EBF16 = 1 << 33
- hwcap2_CSSC = 1 << 34
- hwcap2_RPRFM = 1 << 35
- hwcap2_SVE2P1 = 1 << 36
- hwcap2_SME2 = 1 << 37
- hwcap2_SME2P1 = 1 << 38
- hwcap2_SME_I16I32 = 1 << 39
- hwcap2_SME_BI32I32 = 1 << 40
- hwcap2_SME_B16B16 = 1 << 41
- hwcap2_SME_F16F16 = 1 << 42
- hwcap2_MOPS = 1 << 43
- hwcap2_HBC = 1 << 44
- hwcap2_SVE_B16B16 = 1 << 45
- hwcap2_LRCPC3 = 1 << 46
- hwcap2_LSE128 = 1 << 47
- hwcap2_FPMR = 1 << 48
- hwcap2_LUT = 1 << 49
- hwcap2_FAMINMAX = 1 << 50
- hwcap2_F8CVT = 1 << 51
- hwcap2_F8FMA = 1 << 52
- hwcap2_F8DP4 = 1 << 53
- hwcap2_F8DP2 = 1 << 54
- hwcap2_F8E4M3 = 1 << 55
- hwcap2_F8E5M2 = 1 << 56
- hwcap2_SME_LUTV2 = 1 << 57
- hwcap2_SME_F8F16 = 1 << 58
- hwcap2_SME_F8F32 = 1 << 59
- hwcap2_SME_SF8FMA = 1 << 60
- hwcap2_SME_SF8DP4 = 1 << 61
- hwcap2_SME_SF8DP2 = 1 << 62
- hwcap2_POE = 1 << 63
- )
- func detectOS(c *CPUInfo) bool {
- // For now assuming no hyperthreading is reasonable.
- c.LogicalCores = runtime.NumCPU()
- c.PhysicalCores = c.LogicalCores
- c.ThreadsPerCore = 1
- if hwcap == 0 {
- // We did not get values from the runtime.
- // Try reading /proc/self/auxv
- // From https://github.com/golang/sys
- const (
- _AT_HWCAP = 16
- _AT_HWCAP2 = 26
- uintSize = int(32 << (^uint(0) >> 63))
- )
- buf, err := ioutil.ReadFile("/proc/self/auxv")
- if err != nil {
- // e.g. on android /proc/self/auxv is not accessible, so silently
- // ignore the error and leave Initialized = false. On some
- // architectures (e.g. arm64) doinit() implements a fallback
- // readout and will set Initialized = true again.
- return false
- }
- bo := binary.LittleEndian
- for len(buf) >= 2*(uintSize/8) {
- var tag, val uint
- switch uintSize {
- case 32:
- tag = uint(bo.Uint32(buf[0:]))
- val = uint(bo.Uint32(buf[4:]))
- buf = buf[8:]
- case 64:
- tag = uint(bo.Uint64(buf[0:]))
- val = uint(bo.Uint64(buf[8:]))
- buf = buf[16:]
- }
- switch tag {
- case _AT_HWCAP:
- hwcap = val
- case _AT_HWCAP2:
- // Not used
- }
- }
- if hwcap == 0 {
- return false
- }
- }
- // HWCap was populated by the runtime from the auxiliary vector.
- // Use HWCap information since reading aarch64 system registers
- // is not supported in user space on older linux kernels.
- c.featureSet.setIf(isSet(hwcap, hwcap_AES), AESARM)
- c.featureSet.setIf(isSet(hwcap, hwcap_ASIMD), ASIMD)
- c.featureSet.setIf(isSet(hwcap, hwcap_ASIMDDP), ASIMDDP)
- c.featureSet.setIf(isSet(hwcap, hwcap_ASIMDHP), ASIMDHP)
- c.featureSet.setIf(isSet(hwcap, hwcap_ASIMDRDM), ASIMDRDM)
- c.featureSet.setIf(isSet(hwcap, hwcap_CPUID), ARMCPUID)
- c.featureSet.setIf(isSet(hwcap, hwcap_CRC32), CRC32)
- c.featureSet.setIf(isSet(hwcap, hwcap_DCPOP), DCPOP)
- c.featureSet.setIf(isSet(hwcap, hwcap_EVTSTRM), EVTSTRM)
- c.featureSet.setIf(isSet(hwcap, hwcap_FCMA), FCMA)
- c.featureSet.setIf(isSet(hwcap, hwcap_ASIMDFHM), FHM)
- c.featureSet.setIf(isSet(hwcap, hwcap_FP), FP)
- c.featureSet.setIf(isSet(hwcap, hwcap_FPHP), FPHP)
- c.featureSet.setIf(isSet(hwcap, hwcap_JSCVT), JSCVT)
- c.featureSet.setIf(isSet(hwcap, hwcap_LRCPC), LRCPC)
- c.featureSet.setIf(isSet(hwcap, hwcap_PMULL), PMULL)
- c.featureSet.setIf(isSet(hwcap, hwcap2_RNG), RNDR)
- // c.featureSet.setIf(isSet(hwcap, hwcap_), TLB)
- // c.featureSet.setIf(isSet(hwcap, hwcap_), TS)
- c.featureSet.setIf(isSet(hwcap, hwcap_SHA1), SHA1)
- c.featureSet.setIf(isSet(hwcap, hwcap_SHA2), SHA2)
- c.featureSet.setIf(isSet(hwcap, hwcap_SHA3), SHA3)
- c.featureSet.setIf(isSet(hwcap, hwcap_SHA512), SHA512)
- c.featureSet.setIf(isSet(hwcap, hwcap_SM3), SM3)
- c.featureSet.setIf(isSet(hwcap, hwcap_SM4), SM4)
- c.featureSet.setIf(isSet(hwcap, hwcap_SVE), SVE)
- // The Samsung S9+ kernel reports support for atomics, but not all cores
- // actually support them, resulting in SIGILL. See issue #28431.
- // TODO(elias.naur): Only disable the optimization on bad chipsets on android.
- c.featureSet.setIf(isSet(hwcap, hwcap_ATOMICS) && runtime.GOOS != "android", ATOMICS)
- return true
- }
- func isSet(hwc uint, value uint) bool {
- return hwc&value != 0
- }
|