git.sr.ht/~pingoo/stdx@v0.0.0-20240218134121-094174641f6e/cpuinfo/detect_arm64.go (about)

     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 cpuinfo
     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  }