gtsocial-umbx

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs | README | LICENSE

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 }