| // Copyright (c) 2015 Klaus Post, released under MIT License. See LICENSE file. |
| |
| //go:build arm64 && !gccgo && !noasm && !appengine |
| // +build arm64,!gccgo,!noasm,!appengine |
| |
| package cpuid |
| |
| import "runtime" |
| |
| func getMidr() (midr uint64) |
| func getProcFeatures() (procFeatures uint64) |
| func getInstAttributes() (instAttrReg0, instAttrReg1 uint64) |
| |
| func initCPU() { |
| cpuid = func(uint32) (a, b, c, d uint32) { return 0, 0, 0, 0 } |
| cpuidex = func(x, y uint32) (a, b, c, d uint32) { return 0, 0, 0, 0 } |
| xgetbv = func(uint32) (a, b uint32) { return 0, 0 } |
| rdtscpAsm = func() (a, b, c, d uint32) { return 0, 0, 0, 0 } |
| } |
| |
| func addInfo(c *CPUInfo, safe bool) { |
| // Seems to be safe to assume on ARM64 |
| c.CacheLine = 64 |
| detectOS(c) |
| |
| // ARM64 disabled since it may crash if interrupt is not intercepted by OS. |
| if safe && !c.Supports(ARMCPUID) && runtime.GOOS != "freebsd" { |
| return |
| } |
| midr := getMidr() |
| |
| // MIDR_EL1 - Main ID Register |
| // https://developer.arm.com/docs/ddi0595/h/aarch64-system-registers/midr_el1 |
| // x--------------------------------------------------x |
| // | Name | bits | visible | |
| // |--------------------------------------------------| |
| // | Implementer | [31-24] | y | |
| // |--------------------------------------------------| |
| // | Variant | [23-20] | y | |
| // |--------------------------------------------------| |
| // | Architecture | [19-16] | y | |
| // |--------------------------------------------------| |
| // | PartNum | [15-4] | y | |
| // |--------------------------------------------------| |
| // | Revision | [3-0] | y | |
| // x--------------------------------------------------x |
| |
| switch (midr >> 24) & 0xff { |
| case 0xC0: |
| c.VendorString = "Ampere Computing" |
| c.VendorID = Ampere |
| case 0x41: |
| c.VendorString = "Arm Limited" |
| c.VendorID = ARM |
| case 0x42: |
| c.VendorString = "Broadcom Corporation" |
| c.VendorID = Broadcom |
| case 0x43: |
| c.VendorString = "Cavium Inc" |
| c.VendorID = Cavium |
| case 0x44: |
| c.VendorString = "Digital Equipment Corporation" |
| c.VendorID = DEC |
| case 0x46: |
| c.VendorString = "Fujitsu Ltd" |
| c.VendorID = Fujitsu |
| case 0x49: |
| c.VendorString = "Infineon Technologies AG" |
| c.VendorID = Infineon |
| case 0x4D: |
| c.VendorString = "Motorola or Freescale Semiconductor Inc" |
| c.VendorID = Motorola |
| case 0x4E: |
| c.VendorString = "NVIDIA Corporation" |
| c.VendorID = NVIDIA |
| case 0x50: |
| c.VendorString = "Applied Micro Circuits Corporation" |
| c.VendorID = AMCC |
| case 0x51: |
| c.VendorString = "Qualcomm Inc" |
| c.VendorID = Qualcomm |
| case 0x56: |
| c.VendorString = "Marvell International Ltd" |
| c.VendorID = Marvell |
| case 0x69: |
| c.VendorString = "Intel Corporation" |
| c.VendorID = Intel |
| } |
| |
| // Lower 4 bits: Architecture |
| // Architecture Meaning |
| // 0b0001 Armv4. |
| // 0b0010 Armv4T. |
| // 0b0011 Armv5 (obsolete). |
| // 0b0100 Armv5T. |
| // 0b0101 Armv5TE. |
| // 0b0110 Armv5TEJ. |
| // 0b0111 Armv6. |
| // 0b1111 Architectural features are individually identified in the ID_* registers, see 'ID registers'. |
| // Upper 4 bit: Variant |
| // An IMPLEMENTATION DEFINED variant number. |
| // Typically, this field is used to distinguish between different product variants, or major revisions of a product. |
| c.Family = int(midr>>16) & 0xff |
| |
| // PartNum, bits [15:4] |
| // An IMPLEMENTATION DEFINED primary part number for the device. |
| // On processors implemented by Arm, if the top four bits of the primary |
| // part number are 0x0 or 0x7, the variant and architecture are encoded differently. |
| // Revision, bits [3:0] |
| // An IMPLEMENTATION DEFINED revision number for the device. |
| c.Model = int(midr) & 0xffff |
| |
| procFeatures := getProcFeatures() |
| |
| // ID_AA64PFR0_EL1 - Processor Feature Register 0 |
| // x--------------------------------------------------x |
| // | Name | bits | visible | |
| // |--------------------------------------------------| |
| // | DIT | [51-48] | y | |
| // |--------------------------------------------------| |
| // | SVE | [35-32] | y | |
| // |--------------------------------------------------| |
| // | GIC | [27-24] | n | |
| // |--------------------------------------------------| |
| // | AdvSIMD | [23-20] | y | |
| // |--------------------------------------------------| |
| // | FP | [19-16] | y | |
| // |--------------------------------------------------| |
| // | EL3 | [15-12] | n | |
| // |--------------------------------------------------| |
| // | EL2 | [11-8] | n | |
| // |--------------------------------------------------| |
| // | EL1 | [7-4] | n | |
| // |--------------------------------------------------| |
| // | EL0 | [3-0] | n | |
| // x--------------------------------------------------x |
| |
| var f flagSet |
| // if procFeatures&(0xf<<48) != 0 { |
| // fmt.Println("DIT") |
| // } |
| f.setIf(procFeatures&(0xf<<32) != 0, SVE) |
| if procFeatures&(0xf<<20) != 15<<20 { |
| f.set(ASIMD) |
| // https://developer.arm.com/docs/ddi0595/b/aarch64-system-registers/id_aa64pfr0_el1 |
| // 0b0001 --> As for 0b0000, and also includes support for half-precision floating-point arithmetic. |
| f.setIf(procFeatures&(0xf<<20) == 1<<20, FPHP, ASIMDHP) |
| } |
| f.setIf(procFeatures&(0xf<<16) != 0, FP) |
| |
| instAttrReg0, instAttrReg1 := getInstAttributes() |
| |
| // https://developer.arm.com/docs/ddi0595/b/aarch64-system-registers/id_aa64isar0_el1 |
| // |
| // ID_AA64ISAR0_EL1 - Instruction Set Attribute Register 0 |
| // x--------------------------------------------------x |
| // | Name | bits | visible | |
| // |--------------------------------------------------| |
| // | TS | [55-52] | y | |
| // |--------------------------------------------------| |
| // | FHM | [51-48] | y | |
| // |--------------------------------------------------| |
| // | DP | [47-44] | y | |
| // |--------------------------------------------------| |
| // | SM4 | [43-40] | y | |
| // |--------------------------------------------------| |
| // | SM3 | [39-36] | y | |
| // |--------------------------------------------------| |
| // | SHA3 | [35-32] | y | |
| // |--------------------------------------------------| |
| // | RDM | [31-28] | y | |
| // |--------------------------------------------------| |
| // | ATOMICS | [23-20] | y | |
| // |--------------------------------------------------| |
| // | CRC32 | [19-16] | y | |
| // |--------------------------------------------------| |
| // | SHA2 | [15-12] | y | |
| // |--------------------------------------------------| |
| // | SHA1 | [11-8] | y | |
| // |--------------------------------------------------| |
| // | AES | [7-4] | y | |
| // x--------------------------------------------------x |
| |
| // if instAttrReg0&(0xf<<52) != 0 { |
| // fmt.Println("TS") |
| // } |
| // if instAttrReg0&(0xf<<48) != 0 { |
| // fmt.Println("FHM") |
| // } |
| f.setIf(instAttrReg0&(0xf<<44) != 0, ASIMDDP) |
| f.setIf(instAttrReg0&(0xf<<40) != 0, SM4) |
| f.setIf(instAttrReg0&(0xf<<36) != 0, SM3) |
| f.setIf(instAttrReg0&(0xf<<32) != 0, SHA3) |
| f.setIf(instAttrReg0&(0xf<<28) != 0, ASIMDRDM) |
| f.setIf(instAttrReg0&(0xf<<20) != 0, ATOMICS) |
| f.setIf(instAttrReg0&(0xf<<16) != 0, CRC32) |
| f.setIf(instAttrReg0&(0xf<<12) != 0, SHA2) |
| // https://developer.arm.com/docs/ddi0595/b/aarch64-system-registers/id_aa64isar0_el1 |
| // 0b0010 --> As 0b0001, plus SHA512H, SHA512H2, SHA512SU0, and SHA512SU1 instructions implemented. |
| f.setIf(instAttrReg0&(0xf<<12) == 2<<12, SHA512) |
| f.setIf(instAttrReg0&(0xf<<8) != 0, SHA1) |
| f.setIf(instAttrReg0&(0xf<<4) != 0, AESARM) |
| // https://developer.arm.com/docs/ddi0595/b/aarch64-system-registers/id_aa64isar0_el1 |
| // 0b0010 --> As for 0b0001, plus PMULL/PMULL2 instructions operating on 64-bit data quantities. |
| f.setIf(instAttrReg0&(0xf<<4) == 2<<4, PMULL) |
| |
| // https://developer.arm.com/docs/ddi0595/b/aarch64-system-registers/id_aa64isar1_el1 |
| // |
| // ID_AA64ISAR1_EL1 - Instruction set attribute register 1 |
| // x--------------------------------------------------x |
| // | Name | bits | visible | |
| // |--------------------------------------------------| |
| // | GPI | [31-28] | y | |
| // |--------------------------------------------------| |
| // | GPA | [27-24] | y | |
| // |--------------------------------------------------| |
| // | LRCPC | [23-20] | y | |
| // |--------------------------------------------------| |
| // | FCMA | [19-16] | y | |
| // |--------------------------------------------------| |
| // | JSCVT | [15-12] | y | |
| // |--------------------------------------------------| |
| // | API | [11-8] | y | |
| // |--------------------------------------------------| |
| // | APA | [7-4] | y | |
| // |--------------------------------------------------| |
| // | DPB | [3-0] | y | |
| // x--------------------------------------------------x |
| |
| // if instAttrReg1&(0xf<<28) != 0 { |
| // fmt.Println("GPI") |
| // } |
| f.setIf(instAttrReg1&(0xf<<28) != 24, GPA) |
| f.setIf(instAttrReg1&(0xf<<20) != 0, LRCPC) |
| f.setIf(instAttrReg1&(0xf<<16) != 0, FCMA) |
| f.setIf(instAttrReg1&(0xf<<12) != 0, JSCVT) |
| // if instAttrReg1&(0xf<<8) != 0 { |
| // fmt.Println("API") |
| // } |
| // if instAttrReg1&(0xf<<4) != 0 { |
| // fmt.Println("APA") |
| // } |
| f.setIf(instAttrReg1&(0xf<<0) != 0, DCPOP) |
| |
| // Store |
| c.featureSet.or(f) |
| } |