detect_arm64.go (9940B)
1 // Copyright (c) 2015 Klaus Post, released under MIT License. See LICENSE file. 2 3 //go:build arm64 && !gccgo && !noasm && !appengine 4 // +build arm64,!gccgo,!noasm,!appengine 5 6 package cpuid 7 8 import "runtime" 9 10 func getMidr() (midr uint64) 11 func getProcFeatures() (procFeatures uint64) 12 func getInstAttributes() (instAttrReg0, instAttrReg1 uint64) 13 14 func initCPU() { 15 cpuid = func(uint32) (a, b, c, d uint32) { return 0, 0, 0, 0 } 16 cpuidex = func(x, y uint32) (a, b, c, d uint32) { return 0, 0, 0, 0 } 17 xgetbv = func(uint32) (a, b uint32) { return 0, 0 } 18 rdtscpAsm = func() (a, b, c, d uint32) { return 0, 0, 0, 0 } 19 } 20 21 func addInfo(c *CPUInfo, safe bool) { 22 // Seems to be safe to assume on ARM64 23 c.CacheLine = 64 24 detectOS(c) 25 26 // ARM64 disabled since it may crash if interrupt is not intercepted by OS. 27 if safe && !c.Supports(ARMCPUID) && runtime.GOOS != "freebsd" { 28 return 29 } 30 midr := getMidr() 31 32 // MIDR_EL1 - Main ID Register 33 // https://developer.arm.com/docs/ddi0595/h/aarch64-system-registers/midr_el1 34 // x--------------------------------------------------x 35 // | Name | bits | visible | 36 // |--------------------------------------------------| 37 // | Implementer | [31-24] | y | 38 // |--------------------------------------------------| 39 // | Variant | [23-20] | y | 40 // |--------------------------------------------------| 41 // | Architecture | [19-16] | y | 42 // |--------------------------------------------------| 43 // | PartNum | [15-4] | y | 44 // |--------------------------------------------------| 45 // | Revision | [3-0] | y | 46 // x--------------------------------------------------x 47 48 switch (midr >> 24) & 0xff { 49 case 0xC0: 50 c.VendorString = "Ampere Computing" 51 c.VendorID = Ampere 52 case 0x41: 53 c.VendorString = "Arm Limited" 54 c.VendorID = ARM 55 case 0x42: 56 c.VendorString = "Broadcom Corporation" 57 c.VendorID = Broadcom 58 case 0x43: 59 c.VendorString = "Cavium Inc" 60 c.VendorID = Cavium 61 case 0x44: 62 c.VendorString = "Digital Equipment Corporation" 63 c.VendorID = DEC 64 case 0x46: 65 c.VendorString = "Fujitsu Ltd" 66 c.VendorID = Fujitsu 67 case 0x49: 68 c.VendorString = "Infineon Technologies AG" 69 c.VendorID = Infineon 70 case 0x4D: 71 c.VendorString = "Motorola or Freescale Semiconductor Inc" 72 c.VendorID = Motorola 73 case 0x4E: 74 c.VendorString = "NVIDIA Corporation" 75 c.VendorID = NVIDIA 76 case 0x50: 77 c.VendorString = "Applied Micro Circuits Corporation" 78 c.VendorID = AMCC 79 case 0x51: 80 c.VendorString = "Qualcomm Inc" 81 c.VendorID = Qualcomm 82 case 0x56: 83 c.VendorString = "Marvell International Ltd" 84 c.VendorID = Marvell 85 case 0x69: 86 c.VendorString = "Intel Corporation" 87 c.VendorID = Intel 88 } 89 90 // Lower 4 bits: Architecture 91 // Architecture Meaning 92 // 0b0001 Armv4. 93 // 0b0010 Armv4T. 94 // 0b0011 Armv5 (obsolete). 95 // 0b0100 Armv5T. 96 // 0b0101 Armv5TE. 97 // 0b0110 Armv5TEJ. 98 // 0b0111 Armv6. 99 // 0b1111 Architectural features are individually identified in the ID_* registers, see 'ID registers'. 100 // Upper 4 bit: Variant 101 // An IMPLEMENTATION DEFINED variant number. 102 // Typically, this field is used to distinguish between different product variants, or major revisions of a product. 103 c.Family = int(midr>>16) & 0xff 104 105 // PartNum, bits [15:4] 106 // An IMPLEMENTATION DEFINED primary part number for the device. 107 // On processors implemented by Arm, if the top four bits of the primary 108 // part number are 0x0 or 0x7, the variant and architecture are encoded differently. 109 // Revision, bits [3:0] 110 // An IMPLEMENTATION DEFINED revision number for the device. 111 c.Model = int(midr) & 0xffff 112 113 procFeatures := getProcFeatures() 114 115 // ID_AA64PFR0_EL1 - Processor Feature Register 0 116 // x--------------------------------------------------x 117 // | Name | bits | visible | 118 // |--------------------------------------------------| 119 // | DIT | [51-48] | y | 120 // |--------------------------------------------------| 121 // | SVE | [35-32] | y | 122 // |--------------------------------------------------| 123 // | GIC | [27-24] | n | 124 // |--------------------------------------------------| 125 // | AdvSIMD | [23-20] | y | 126 // |--------------------------------------------------| 127 // | FP | [19-16] | y | 128 // |--------------------------------------------------| 129 // | EL3 | [15-12] | n | 130 // |--------------------------------------------------| 131 // | EL2 | [11-8] | n | 132 // |--------------------------------------------------| 133 // | EL1 | [7-4] | n | 134 // |--------------------------------------------------| 135 // | EL0 | [3-0] | n | 136 // x--------------------------------------------------x 137 138 var f flagSet 139 // if procFeatures&(0xf<<48) != 0 { 140 // fmt.Println("DIT") 141 // } 142 f.setIf(procFeatures&(0xf<<32) != 0, SVE) 143 if procFeatures&(0xf<<20) != 15<<20 { 144 f.set(ASIMD) 145 // https://developer.arm.com/docs/ddi0595/b/aarch64-system-registers/id_aa64pfr0_el1 146 // 0b0001 --> As for 0b0000, and also includes support for half-precision floating-point arithmetic. 147 f.setIf(procFeatures&(0xf<<20) == 1<<20, FPHP, ASIMDHP) 148 } 149 f.setIf(procFeatures&(0xf<<16) != 0, FP) 150 151 instAttrReg0, instAttrReg1 := getInstAttributes() 152 153 // https://developer.arm.com/docs/ddi0595/b/aarch64-system-registers/id_aa64isar0_el1 154 // 155 // ID_AA64ISAR0_EL1 - Instruction Set Attribute Register 0 156 // x--------------------------------------------------x 157 // | Name | bits | visible | 158 // |--------------------------------------------------| 159 // | TS | [55-52] | y | 160 // |--------------------------------------------------| 161 // | FHM | [51-48] | y | 162 // |--------------------------------------------------| 163 // | DP | [47-44] | y | 164 // |--------------------------------------------------| 165 // | SM4 | [43-40] | y | 166 // |--------------------------------------------------| 167 // | SM3 | [39-36] | y | 168 // |--------------------------------------------------| 169 // | SHA3 | [35-32] | y | 170 // |--------------------------------------------------| 171 // | RDM | [31-28] | y | 172 // |--------------------------------------------------| 173 // | ATOMICS | [23-20] | y | 174 // |--------------------------------------------------| 175 // | CRC32 | [19-16] | y | 176 // |--------------------------------------------------| 177 // | SHA2 | [15-12] | y | 178 // |--------------------------------------------------| 179 // | SHA1 | [11-8] | y | 180 // |--------------------------------------------------| 181 // | AES | [7-4] | y | 182 // x--------------------------------------------------x 183 184 // if instAttrReg0&(0xf<<52) != 0 { 185 // fmt.Println("TS") 186 // } 187 // if instAttrReg0&(0xf<<48) != 0 { 188 // fmt.Println("FHM") 189 // } 190 f.setIf(instAttrReg0&(0xf<<44) != 0, ASIMDDP) 191 f.setIf(instAttrReg0&(0xf<<40) != 0, SM4) 192 f.setIf(instAttrReg0&(0xf<<36) != 0, SM3) 193 f.setIf(instAttrReg0&(0xf<<32) != 0, SHA3) 194 f.setIf(instAttrReg0&(0xf<<28) != 0, ASIMDRDM) 195 f.setIf(instAttrReg0&(0xf<<20) != 0, ATOMICS) 196 f.setIf(instAttrReg0&(0xf<<16) != 0, CRC32) 197 f.setIf(instAttrReg0&(0xf<<12) != 0, SHA2) 198 // https://developer.arm.com/docs/ddi0595/b/aarch64-system-registers/id_aa64isar0_el1 199 // 0b0010 --> As 0b0001, plus SHA512H, SHA512H2, SHA512SU0, and SHA512SU1 instructions implemented. 200 f.setIf(instAttrReg0&(0xf<<12) == 2<<12, SHA512) 201 f.setIf(instAttrReg0&(0xf<<8) != 0, SHA1) 202 f.setIf(instAttrReg0&(0xf<<4) != 0, AESARM) 203 // https://developer.arm.com/docs/ddi0595/b/aarch64-system-registers/id_aa64isar0_el1 204 // 0b0010 --> As for 0b0001, plus PMULL/PMULL2 instructions operating on 64-bit data quantities. 205 f.setIf(instAttrReg0&(0xf<<4) == 2<<4, PMULL) 206 207 // https://developer.arm.com/docs/ddi0595/b/aarch64-system-registers/id_aa64isar1_el1 208 // 209 // ID_AA64ISAR1_EL1 - Instruction set attribute register 1 210 // x--------------------------------------------------x 211 // | Name | bits | visible | 212 // |--------------------------------------------------| 213 // | GPI | [31-28] | y | 214 // |--------------------------------------------------| 215 // | GPA | [27-24] | y | 216 // |--------------------------------------------------| 217 // | LRCPC | [23-20] | y | 218 // |--------------------------------------------------| 219 // | FCMA | [19-16] | y | 220 // |--------------------------------------------------| 221 // | JSCVT | [15-12] | y | 222 // |--------------------------------------------------| 223 // | API | [11-8] | y | 224 // |--------------------------------------------------| 225 // | APA | [7-4] | y | 226 // |--------------------------------------------------| 227 // | DPB | [3-0] | y | 228 // x--------------------------------------------------x 229 230 // if instAttrReg1&(0xf<<28) != 0 { 231 // fmt.Println("GPI") 232 // } 233 f.setIf(instAttrReg1&(0xf<<28) != 24, GPA) 234 f.setIf(instAttrReg1&(0xf<<20) != 0, LRCPC) 235 f.setIf(instAttrReg1&(0xf<<16) != 0, FCMA) 236 f.setIf(instAttrReg1&(0xf<<12) != 0, JSCVT) 237 // if instAttrReg1&(0xf<<8) != 0 { 238 // fmt.Println("API") 239 // } 240 // if instAttrReg1&(0xf<<4) != 0 { 241 // fmt.Println("APA") 242 // } 243 f.setIf(instAttrReg1&(0xf<<0) != 0, DCPOP) 244 245 // Store 246 c.featureSet.or(f) 247 }