os_linux_arm64.go (3972B)
1 // Copyright (c) 2020 Klaus Post, released under MIT License. See LICENSE file. 2 3 // Copyright 2018 The Go Authors. All rights reserved. 4 // Use of this source code is governed by a BSD-style 5 // license that can be found in the LICENSE file located 6 // here https://github.com/golang/sys/blob/master/LICENSE 7 8 package cpuid 9 10 import ( 11 "encoding/binary" 12 "io/ioutil" 13 "runtime" 14 ) 15 16 // HWCAP bits. 17 const ( 18 hwcap_FP = 1 << 0 19 hwcap_ASIMD = 1 << 1 20 hwcap_EVTSTRM = 1 << 2 21 hwcap_AES = 1 << 3 22 hwcap_PMULL = 1 << 4 23 hwcap_SHA1 = 1 << 5 24 hwcap_SHA2 = 1 << 6 25 hwcap_CRC32 = 1 << 7 26 hwcap_ATOMICS = 1 << 8 27 hwcap_FPHP = 1 << 9 28 hwcap_ASIMDHP = 1 << 10 29 hwcap_CPUID = 1 << 11 30 hwcap_ASIMDRDM = 1 << 12 31 hwcap_JSCVT = 1 << 13 32 hwcap_FCMA = 1 << 14 33 hwcap_LRCPC = 1 << 15 34 hwcap_DCPOP = 1 << 16 35 hwcap_SHA3 = 1 << 17 36 hwcap_SM3 = 1 << 18 37 hwcap_SM4 = 1 << 19 38 hwcap_ASIMDDP = 1 << 20 39 hwcap_SHA512 = 1 << 21 40 hwcap_SVE = 1 << 22 41 hwcap_ASIMDFHM = 1 << 23 42 ) 43 44 func detectOS(c *CPUInfo) bool { 45 // For now assuming no hyperthreading is reasonable. 46 c.LogicalCores = runtime.NumCPU() 47 c.PhysicalCores = c.LogicalCores 48 c.ThreadsPerCore = 1 49 if hwcap == 0 { 50 // We did not get values from the runtime. 51 // Try reading /proc/self/auxv 52 53 // From https://github.com/golang/sys 54 const ( 55 _AT_HWCAP = 16 56 _AT_HWCAP2 = 26 57 58 uintSize = int(32 << (^uint(0) >> 63)) 59 ) 60 61 buf, err := ioutil.ReadFile("/proc/self/auxv") 62 if err != nil { 63 // e.g. on android /proc/self/auxv is not accessible, so silently 64 // ignore the error and leave Initialized = false. On some 65 // architectures (e.g. arm64) doinit() implements a fallback 66 // readout and will set Initialized = true again. 67 return false 68 } 69 bo := binary.LittleEndian 70 for len(buf) >= 2*(uintSize/8) { 71 var tag, val uint 72 switch uintSize { 73 case 32: 74 tag = uint(bo.Uint32(buf[0:])) 75 val = uint(bo.Uint32(buf[4:])) 76 buf = buf[8:] 77 case 64: 78 tag = uint(bo.Uint64(buf[0:])) 79 val = uint(bo.Uint64(buf[8:])) 80 buf = buf[16:] 81 } 82 switch tag { 83 case _AT_HWCAP: 84 hwcap = val 85 case _AT_HWCAP2: 86 // Not used 87 } 88 } 89 if hwcap == 0 { 90 return false 91 } 92 } 93 94 // HWCap was populated by the runtime from the auxiliary vector. 95 // Use HWCap information since reading aarch64 system registers 96 // is not supported in user space on older linux kernels. 97 c.featureSet.setIf(isSet(hwcap, hwcap_AES), AESARM) 98 c.featureSet.setIf(isSet(hwcap, hwcap_ASIMD), ASIMD) 99 c.featureSet.setIf(isSet(hwcap, hwcap_ASIMDDP), ASIMDDP) 100 c.featureSet.setIf(isSet(hwcap, hwcap_ASIMDHP), ASIMDHP) 101 c.featureSet.setIf(isSet(hwcap, hwcap_ASIMDRDM), ASIMDRDM) 102 c.featureSet.setIf(isSet(hwcap, hwcap_CPUID), ARMCPUID) 103 c.featureSet.setIf(isSet(hwcap, hwcap_CRC32), CRC32) 104 c.featureSet.setIf(isSet(hwcap, hwcap_DCPOP), DCPOP) 105 c.featureSet.setIf(isSet(hwcap, hwcap_EVTSTRM), EVTSTRM) 106 c.featureSet.setIf(isSet(hwcap, hwcap_FCMA), FCMA) 107 c.featureSet.setIf(isSet(hwcap, hwcap_FP), FP) 108 c.featureSet.setIf(isSet(hwcap, hwcap_FPHP), FPHP) 109 c.featureSet.setIf(isSet(hwcap, hwcap_JSCVT), JSCVT) 110 c.featureSet.setIf(isSet(hwcap, hwcap_LRCPC), LRCPC) 111 c.featureSet.setIf(isSet(hwcap, hwcap_PMULL), PMULL) 112 c.featureSet.setIf(isSet(hwcap, hwcap_SHA1), SHA1) 113 c.featureSet.setIf(isSet(hwcap, hwcap_SHA2), SHA2) 114 c.featureSet.setIf(isSet(hwcap, hwcap_SHA3), SHA3) 115 c.featureSet.setIf(isSet(hwcap, hwcap_SHA512), SHA512) 116 c.featureSet.setIf(isSet(hwcap, hwcap_SM3), SM3) 117 c.featureSet.setIf(isSet(hwcap, hwcap_SM4), SM4) 118 c.featureSet.setIf(isSet(hwcap, hwcap_SVE), SVE) 119 120 // The Samsung S9+ kernel reports support for atomics, but not all cores 121 // actually support them, resulting in SIGILL. See issue #28431. 122 // TODO(elias.naur): Only disable the optimization on bad chipsets on android. 123 c.featureSet.setIf(isSet(hwcap, hwcap_ATOMICS) && runtime.GOOS != "android", ATOMICS) 124 125 return true 126 } 127 128 func isSet(hwc uint, value uint) bool { 129 return hwc&value != 0 130 }