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