os_darwin_arm64.go raw

   1  // Copyright (c) 2020 Klaus Post, released under MIT License. See LICENSE file.
   2  
   3  package cpuid
   4  
   5  import (
   6  	"runtime"
   7  	"strings"
   8  
   9  	"golang.org/x/sys/unix"
  10  )
  11  
  12  func detectOS(c *CPUInfo) bool {
  13  	if runtime.GOOS != "ios" {
  14  		tryToFillCPUInfoFomSysctl(c)
  15  	}
  16  	// There are no hw.optional sysctl values for the below features on Mac OS 11.0
  17  	// to detect their supported state dynamically. Assume the CPU features that
  18  	// Apple Silicon M1 supports to be available as a minimal set of features
  19  	// to all Go programs running on darwin/arm64.
  20  	// TODO: Add more if we know them.
  21  	c.featureSet.setIf(runtime.GOOS != "ios", AESARM, PMULL, SHA1, SHA2)
  22  
  23  	return true
  24  }
  25  
  26  func sysctlGetBool(name string) bool {
  27  	value, err := unix.SysctlUint32(name)
  28  	if err != nil {
  29  		return false
  30  	}
  31  	return value != 0
  32  }
  33  
  34  func sysctlGetString(name string) string {
  35  	value, err := unix.Sysctl(name)
  36  	if err != nil {
  37  		return ""
  38  	}
  39  	return value
  40  }
  41  
  42  func sysctlGetInt(unknown int, names ...string) int {
  43  	for _, name := range names {
  44  		value, err := unix.SysctlUint32(name)
  45  		if err != nil {
  46  			continue
  47  		}
  48  		if value != 0 {
  49  			return int(value)
  50  		}
  51  	}
  52  	return unknown
  53  }
  54  
  55  func sysctlGetInt64(unknown int, names ...string) int {
  56  	for _, name := range names {
  57  		value64, err := unix.SysctlUint64(name)
  58  		if err != nil {
  59  			continue
  60  		}
  61  		if int(value64) != unknown {
  62  			return int(value64)
  63  		}
  64  	}
  65  	return unknown
  66  }
  67  
  68  func setFeature(c *CPUInfo, feature FeatureID, aliases ...string) {
  69  	for _, alias := range aliases {
  70  		set := sysctlGetBool(alias)
  71  		c.featureSet.setIf(set, feature)
  72  		if set {
  73  			break
  74  		}
  75  	}
  76  }
  77  
  78  func tryToFillCPUInfoFomSysctl(c *CPUInfo) {
  79  	c.BrandName = sysctlGetString("machdep.cpu.brand_string")
  80  
  81  	if len(c.BrandName) != 0 {
  82  		c.VendorString = strings.Fields(c.BrandName)[0]
  83  	}
  84  
  85  	c.PhysicalCores = sysctlGetInt(runtime.NumCPU(), "hw.physicalcpu")
  86  	c.ThreadsPerCore = sysctlGetInt(1, "machdep.cpu.thread_count", "kern.num_threads") /
  87  		sysctlGetInt(1, "hw.physicalcpu")
  88  	c.LogicalCores = sysctlGetInt(runtime.NumCPU(), "machdep.cpu.core_count")
  89  	c.Family = sysctlGetInt(0, "machdep.cpu.family", "hw.cpufamily")
  90  	c.Model = sysctlGetInt(0, "machdep.cpu.model")
  91  	c.CacheLine = sysctlGetInt64(0, "hw.cachelinesize")
  92  	c.Cache.L1I = sysctlGetInt64(-1, "hw.l1icachesize")
  93  	c.Cache.L1D = sysctlGetInt64(-1, "hw.l1dcachesize")
  94  	c.Cache.L2 = sysctlGetInt64(-1, "hw.l2cachesize")
  95  	c.Cache.L3 = sysctlGetInt64(-1, "hw.l3cachesize")
  96  
  97  	// ARM features:
  98  	//
  99  	// Note: On some Apple Silicon system, some feats have aliases. See:
 100  	// https://developer.apple.com/documentation/kernel/1387446-sysctlbyname/determining_instruction_set_characteristics
 101  	// When so, we look at all aliases and consider a feature available when at least one identifier matches.
 102  	setFeature(c, AESARM, "hw.optional.arm.FEAT_AES")                                   // AES instructions
 103  	setFeature(c, ASIMD, "hw.optional.arm.AdvSIMD", "hw.optional.neon")                 // Advanced SIMD
 104  	setFeature(c, ASIMDDP, "hw.optional.arm.FEAT_DotProd")                              // SIMD Dot Product
 105  	setFeature(c, ASIMDHP, "hw.optional.arm.AdvSIMD_HPFPCvt", "hw.optional.neon_hpfp")  // Advanced SIMD half-precision floating point
 106  	setFeature(c, ASIMDRDM, "hw.optional.arm.FEAT_RDM")                                 // Rounding Double Multiply Accumulate/Subtract
 107  	setFeature(c, ATOMICS, "hw.optional.arm.FEAT_LSE", "hw.optional.armv8_1_atomics")   // Large System Extensions (LSE)
 108  	setFeature(c, CRC32, "hw.optional.arm.FEAT_CRC32", "hw.optional.armv8_crc32")       // CRC32/CRC32C instructions
 109  	setFeature(c, DCPOP, "hw.optional.arm.FEAT_DPB")                                    // Data cache clean to Point of Persistence (DC CVAP)
 110  	setFeature(c, EVTSTRM, "hw.optional.arm.FEAT_ECV")                                  // Generic timer
 111  	setFeature(c, FCMA, "hw.optional.arm.FEAT_FCMA", "hw.optional.armv8_3_compnum")     // Floating point complex number addition and multiplication
 112  	setFeature(c, FHM, "hw.optional.armv8_2_fhm", "hw.optional.arm.FEAT_FHM")           // FMLAL and FMLSL instructions
 113  	setFeature(c, FP, "hw.optional.floatingpoint")                                      // Single-precision and double-precision floating point
 114  	setFeature(c, FPHP, "hw.optional.arm.FEAT_FP16", "hw.optional.neon_fp16")           // Half-precision floating point
 115  	setFeature(c, GPA, "hw.optional.arm.FEAT_PAuth")                                    // Generic Pointer Authentication
 116  	setFeature(c, JSCVT, "hw.optional.arm.FEAT_JSCVT")                                  // Javascript-style double->int convert (FJCVTZS)
 117  	setFeature(c, LRCPC, "hw.optional.arm.FEAT_LRCPC")                                  // Weaker release consistency (LDAPR, etc)
 118  	setFeature(c, PMULL, "hw.optional.arm.FEAT_PMULL")                                  // Polynomial Multiply instructions (PMULL/PMULL2)
 119  	setFeature(c, RNDR, "hw.optional.arm.FEAT_RNG")                                     // Random Number instructions
 120  	setFeature(c, TLB, "hw.optional.arm.FEAT_TLBIOS", "hw.optional.arm.FEAT_TLBIRANGE") // Outer Shareable and TLB range maintenance instructions
 121  	setFeature(c, TS, "hw.optional.arm.FEAT_FlagM", "hw.optional.arm.FEAT_FlagM2")      // Flag manipulation instructions
 122  	setFeature(c, SHA1, "hw.optional.arm.FEAT_SHA1")                                    // SHA-1 instructions (SHA1C, etc)
 123  	setFeature(c, SHA2, "hw.optional.arm.FEAT_SHA256")                                  // SHA-2 instructions (SHA256H, etc)
 124  	setFeature(c, SHA3, "hw.optional.arm.FEAT_SHA3")                                    // SHA-3 instructions (EOR3, RAXI, XAR, BCAX)
 125  	setFeature(c, SHA512, "hw.optional.arm.FEAT_SHA512")                                // SHA512 instructions
 126  	setFeature(c, SM3, "hw.optional.arm.FEAT_SM3")                                      // SM3 instructions
 127  	setFeature(c, SM4, "hw.optional.arm.FEAT_SM4")                                      // SM4 instructions
 128  	setFeature(c, SVE, "hw.optional.arm.FEAT_SVE")                                      // Scalable Vector Extension
 129  }
 130