diff options
author | Cherry Zhang <cherryyz@google.com> | 2020-10-28 09:12:20 -0400 |
---|---|---|
committer | Cherry Zhang <cherryyz@google.com> | 2020-10-28 09:12:20 -0400 |
commit | a16e30d162c1c7408db7821e7b9513cefa09c6ca (patch) | |
tree | af752ba9ba44c547df39bb0af9bff79f610ba9d5 /src/internal/cpu/cpu_arm64.go | |
parent | 91e4d2d57bc341dd82c98247117114c851380aef (diff) | |
parent | cf6cfba4d5358404dd890f6025e573a4b2156543 (diff) | |
download | go-git-dev.link.tar.gz |
[dev.link] all: merge branch 'master' into dev.linkdev.link
Clean merge.
Change-Id: Ia7b2808bc649790198d34c226a61d9e569084dc5
Diffstat (limited to 'src/internal/cpu/cpu_arm64.go')
-rw-r--r-- | src/internal/cpu/cpu_arm64.go | 141 |
1 files changed, 67 insertions, 74 deletions
diff --git a/src/internal/cpu/cpu_arm64.go b/src/internal/cpu/cpu_arm64.go index efdb3b9e33..533bea2470 100644 --- a/src/internal/cpu/cpu_arm64.go +++ b/src/internal/cpu/cpu_arm64.go @@ -6,97 +6,90 @@ package cpu const CacheLinePadSize = 64 -// arm64 doesn't have a 'cpuid' equivalent, so we rely on HWCAP/HWCAP2. -// These are initialized by archauxv and should not be changed after they are -// initialized. +// HWCap may be initialized by archauxv and +// should not be changed after it was initialized. var HWCap uint -var HWCap2 uint -// HWCAP/HWCAP2 bits. These are exposed by Linux. +// HWCAP bits. These are exposed by Linux. 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_AES = 1 << 3 + hwcap_PMULL = 1 << 4 + hwcap_SHA1 = 1 << 5 + hwcap_SHA2 = 1 << 6 + hwcap_CRC32 = 1 << 7 + hwcap_ATOMICS = 1 << 8 ) func doinit() { options = []option{ - {Name: "evtstrm", Feature: &ARM64.HasEVTSTRM}, {Name: "aes", Feature: &ARM64.HasAES}, {Name: "pmull", Feature: &ARM64.HasPMULL}, {Name: "sha1", Feature: &ARM64.HasSHA1}, {Name: "sha2", Feature: &ARM64.HasSHA2}, {Name: "crc32", Feature: &ARM64.HasCRC32}, {Name: "atomics", Feature: &ARM64.HasATOMICS}, - {Name: "fphp", Feature: &ARM64.HasFPHP}, - {Name: "asimdhp", Feature: &ARM64.HasASIMDHP}, - {Name: "cpuid", Feature: &ARM64.HasCPUID}, - {Name: "asimdrdm", Feature: &ARM64.HasASIMDRDM}, - {Name: "jscvt", Feature: &ARM64.HasJSCVT}, - {Name: "fcma", Feature: &ARM64.HasFCMA}, - {Name: "lrcpc", Feature: &ARM64.HasLRCPC}, - {Name: "dcpop", Feature: &ARM64.HasDCPOP}, - {Name: "sha3", Feature: &ARM64.HasSHA3}, - {Name: "sm3", Feature: &ARM64.HasSM3}, - {Name: "sm4", Feature: &ARM64.HasSM4}, - {Name: "asimddp", Feature: &ARM64.HasASIMDDP}, - {Name: "sha512", Feature: &ARM64.HasSHA512}, - {Name: "sve", Feature: &ARM64.HasSVE}, - {Name: "asimdfhm", Feature: &ARM64.HasASIMDFHM}, - - // These capabilities should always be enabled on arm64: - {Name: "fp", Feature: &ARM64.HasFP, Required: true}, - {Name: "asimd", Feature: &ARM64.HasASIMD, Required: true}, } - // HWCAP feature bits - ARM64.HasFP = isSet(HWCap, hwcap_FP) - ARM64.HasASIMD = isSet(HWCap, hwcap_ASIMD) - ARM64.HasEVTSTRM = isSet(HWCap, hwcap_EVTSTRM) - ARM64.HasAES = isSet(HWCap, hwcap_AES) - ARM64.HasPMULL = isSet(HWCap, hwcap_PMULL) - ARM64.HasSHA1 = isSet(HWCap, hwcap_SHA1) - ARM64.HasSHA2 = isSet(HWCap, hwcap_SHA2) - ARM64.HasCRC32 = isSet(HWCap, hwcap_CRC32) - ARM64.HasATOMICS = isSet(HWCap, hwcap_ATOMICS) - ARM64.HasFPHP = isSet(HWCap, hwcap_FPHP) - ARM64.HasASIMDHP = isSet(HWCap, hwcap_ASIMDHP) - ARM64.HasCPUID = isSet(HWCap, hwcap_CPUID) - ARM64.HasASIMDRDM = isSet(HWCap, hwcap_ASIMDRDM) - ARM64.HasJSCVT = isSet(HWCap, hwcap_JSCVT) - ARM64.HasFCMA = isSet(HWCap, hwcap_FCMA) - ARM64.HasLRCPC = isSet(HWCap, hwcap_LRCPC) - ARM64.HasDCPOP = isSet(HWCap, hwcap_DCPOP) - ARM64.HasSHA3 = isSet(HWCap, hwcap_SHA3) - ARM64.HasSM3 = isSet(HWCap, hwcap_SM3) - ARM64.HasSM4 = isSet(HWCap, hwcap_SM4) - ARM64.HasASIMDDP = isSet(HWCap, hwcap_ASIMDDP) - ARM64.HasSHA512 = isSet(HWCap, hwcap_SHA512) - ARM64.HasSVE = isSet(HWCap, hwcap_SVE) - ARM64.HasASIMDFHM = isSet(HWCap, hwcap_ASIMDFHM) + switch GOOS { + case "linux", "android": + // HWCap was populated by the runtime from the auxillary vector. + // Use HWCap information since reading aarch64 system registers + // is not supported in user space on older linux kernels. + ARM64.HasAES = isSet(HWCap, hwcap_AES) + ARM64.HasPMULL = isSet(HWCap, hwcap_PMULL) + ARM64.HasSHA1 = isSet(HWCap, hwcap_SHA1) + ARM64.HasSHA2 = isSet(HWCap, hwcap_SHA2) + ARM64.HasCRC32 = isSet(HWCap, hwcap_CRC32) + + // 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. + ARM64.HasATOMICS = isSet(HWCap, hwcap_ATOMICS) && GOOS != "android" + + case "freebsd": + // Retrieve info from system register ID_AA64ISAR0_EL1. + isar0 := getisar0() + + // ID_AA64ISAR0_EL1 + switch extractBits(isar0, 4, 7) { + case 1: + ARM64.HasAES = true + case 2: + ARM64.HasAES = true + ARM64.HasPMULL = true + } + + switch extractBits(isar0, 8, 11) { + case 1: + ARM64.HasSHA1 = true + } + + switch extractBits(isar0, 12, 15) { + case 1, 2: + ARM64.HasSHA2 = true + } + + switch extractBits(isar0, 16, 19) { + case 1: + ARM64.HasCRC32 = true + } + + switch extractBits(isar0, 20, 23) { + case 2: + ARM64.HasATOMICS = true + } + default: + // Other operating systems do not support reading HWCap from auxillary vector + // or reading privileged aarch64 system registers in user space. + } +} + +func extractBits(data uint64, start, end uint) uint { + return (uint)(data>>start) & ((1 << (end - start + 1)) - 1) } func isSet(hwc uint, value uint) bool { return hwc&value != 0 } + +func getisar0() uint64 |