golang.org/x/sys@v0.20.1-0.20240517151509-673e0f94c16d/cpu/cpu_arm64.go (about) 1 // Copyright 2019 The Go Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 package cpu 6 7 import "runtime" 8 9 // cacheLineSize is used to prevent false sharing of cache lines. 10 // We choose 128 because Apple Silicon, a.k.a. M1, has 128-byte cache line size. 11 // It doesn't cost much and is much more future-proof. 12 const cacheLineSize = 128 13 14 func initOptions() { 15 options = []option{ 16 {Name: "fp", Feature: &ARM64.HasFP}, 17 {Name: "asimd", Feature: &ARM64.HasASIMD}, 18 {Name: "evstrm", Feature: &ARM64.HasEVTSTRM}, 19 {Name: "aes", Feature: &ARM64.HasAES}, 20 {Name: "fphp", Feature: &ARM64.HasFPHP}, 21 {Name: "jscvt", Feature: &ARM64.HasJSCVT}, 22 {Name: "lrcpc", Feature: &ARM64.HasLRCPC}, 23 {Name: "pmull", Feature: &ARM64.HasPMULL}, 24 {Name: "sha1", Feature: &ARM64.HasSHA1}, 25 {Name: "sha2", Feature: &ARM64.HasSHA2}, 26 {Name: "sha3", Feature: &ARM64.HasSHA3}, 27 {Name: "sha512", Feature: &ARM64.HasSHA512}, 28 {Name: "sm3", Feature: &ARM64.HasSM3}, 29 {Name: "sm4", Feature: &ARM64.HasSM4}, 30 {Name: "sve", Feature: &ARM64.HasSVE}, 31 {Name: "sve2", Feature: &ARM64.HasSVE2}, 32 {Name: "crc32", Feature: &ARM64.HasCRC32}, 33 {Name: "atomics", Feature: &ARM64.HasATOMICS}, 34 {Name: "asimdhp", Feature: &ARM64.HasASIMDHP}, 35 {Name: "cpuid", Feature: &ARM64.HasCPUID}, 36 {Name: "asimrdm", Feature: &ARM64.HasASIMDRDM}, 37 {Name: "fcma", Feature: &ARM64.HasFCMA}, 38 {Name: "dcpop", Feature: &ARM64.HasDCPOP}, 39 {Name: "asimddp", Feature: &ARM64.HasASIMDDP}, 40 {Name: "asimdfhm", Feature: &ARM64.HasASIMDFHM}, 41 } 42 } 43 44 func archInit() { 45 switch runtime.GOOS { 46 case "freebsd": 47 readARM64Registers() 48 case "linux", "netbsd", "openbsd": 49 doinit() 50 default: 51 // Many platforms don't seem to allow reading these registers. 52 setMinimalFeatures() 53 } 54 } 55 56 // setMinimalFeatures fakes the minimal ARM64 features expected by 57 // TestARM64minimalFeatures. 58 func setMinimalFeatures() { 59 ARM64.HasASIMD = true 60 ARM64.HasFP = true 61 } 62 63 func readARM64Registers() { 64 Initialized = true 65 66 parseARM64SystemRegisters(getisar0(), getisar1(), getpfr0()) 67 } 68 69 func parseARM64SystemRegisters(isar0, isar1, pfr0 uint64) { 70 // ID_AA64ISAR0_EL1 71 switch extractBits(isar0, 4, 7) { 72 case 1: 73 ARM64.HasAES = true 74 case 2: 75 ARM64.HasAES = true 76 ARM64.HasPMULL = true 77 } 78 79 switch extractBits(isar0, 8, 11) { 80 case 1: 81 ARM64.HasSHA1 = true 82 } 83 84 switch extractBits(isar0, 12, 15) { 85 case 1: 86 ARM64.HasSHA2 = true 87 case 2: 88 ARM64.HasSHA2 = true 89 ARM64.HasSHA512 = true 90 } 91 92 switch extractBits(isar0, 16, 19) { 93 case 1: 94 ARM64.HasCRC32 = true 95 } 96 97 switch extractBits(isar0, 20, 23) { 98 case 2: 99 ARM64.HasATOMICS = true 100 } 101 102 switch extractBits(isar0, 28, 31) { 103 case 1: 104 ARM64.HasASIMDRDM = true 105 } 106 107 switch extractBits(isar0, 32, 35) { 108 case 1: 109 ARM64.HasSHA3 = true 110 } 111 112 switch extractBits(isar0, 36, 39) { 113 case 1: 114 ARM64.HasSM3 = true 115 } 116 117 switch extractBits(isar0, 40, 43) { 118 case 1: 119 ARM64.HasSM4 = true 120 } 121 122 switch extractBits(isar0, 44, 47) { 123 case 1: 124 ARM64.HasASIMDDP = true 125 } 126 127 // ID_AA64ISAR1_EL1 128 switch extractBits(isar1, 0, 3) { 129 case 1: 130 ARM64.HasDCPOP = true 131 } 132 133 switch extractBits(isar1, 12, 15) { 134 case 1: 135 ARM64.HasJSCVT = true 136 } 137 138 switch extractBits(isar1, 16, 19) { 139 case 1: 140 ARM64.HasFCMA = true 141 } 142 143 switch extractBits(isar1, 20, 23) { 144 case 1: 145 ARM64.HasLRCPC = true 146 } 147 148 // ID_AA64PFR0_EL1 149 switch extractBits(pfr0, 16, 19) { 150 case 0: 151 ARM64.HasFP = true 152 case 1: 153 ARM64.HasFP = true 154 ARM64.HasFPHP = true 155 } 156 157 switch extractBits(pfr0, 20, 23) { 158 case 0: 159 ARM64.HasASIMD = true 160 case 1: 161 ARM64.HasASIMD = true 162 ARM64.HasASIMDHP = true 163 } 164 165 switch extractBits(pfr0, 32, 35) { 166 case 1: 167 ARM64.HasSVE = true 168 169 parseARM64SVERegister(getzfr0()) 170 } 171 } 172 173 func parseARM64SVERegister(zfr0 uint64) { 174 switch extractBits(zfr0, 0, 3) { 175 case 1: 176 ARM64.HasSVE2 = true 177 } 178 } 179 180 func extractBits(data uint64, start, end uint) uint { 181 return (uint)(data>>start) & ((1 << (end - start + 1)) - 1) 182 }