Skip to content

Commit

Permalink
Add Microarchitecture levels (#92)
Browse files Browse the repository at this point in the history
From https://en.wikipedia.org/wiki/X86-64#Microarchitecture_levels

Example:
```
Name: AMD Ryzen 9 3950X 16-Core Processor
Vendor String: AuthenticAMD
Vendor ID: AMD
PhysicalCores: 16
Threads Per Core: 2
Logical Cores: 32
CPU Family 23 Model: 113
Features: ADX,AESNI,AVX,AVX2,BMI1,BMI2,CLMUL,CLZERO,CMOV,CMPXCHG8,CPBOOST,CX16,F16C,FMA3,FXSR,FXSROPT,HTT,HYPERVISOR,LAHF,LZCNT,MCAOVERFLOW,MMX,MMXEXT,MOVBE,NX,OSXSAVE,POPCNT,RDRAND,RDSEED,RDTSCP,SCE,SHA,SSE,SSE2,SSE3,SSE4,SSE42,SSE4A,SSSE3,SUCCOR,X87,XSAVE
Microarchitecture level: 3
Cacheline bytes: 64
L1 Instruction Cache: 32768 bytes
L1 Data Cache: 32768 bytes
L2 Cache: 524288 bytes
L3 Cache: 16777216 bytes
```
  • Loading branch information
klauspost committed Jan 31, 2022
1 parent cffd0d4 commit eb76847
Show file tree
Hide file tree
Showing 5 changed files with 167 additions and 91 deletions.
1 change: 1 addition & 0 deletions cmd/cpuid/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ func main() {
fmt.Println("Logical Cores:", cpuid.CPU.LogicalCores)
fmt.Println("CPU Family", cpuid.CPU.Family, "Model:", cpuid.CPU.Model)
fmt.Println("Features:", strings.Join(cpuid.CPU.FeatureSet(), ","))
fmt.Println("Microarchitecture level:", cpuid.CPU.X64Level())
fmt.Println("Cacheline bytes:", cpuid.CPU.CacheLine)
fmt.Println("L1 Instruction Cache:", cpuid.CPU.Cache.L1I, "bytes")
fmt.Println("L1 Data Cache:", cpuid.CPU.Cache.L1D, "bytes")
Expand Down
64 changes: 63 additions & 1 deletion cpuid.go
Original file line number Diff line number Diff line change
Expand Up @@ -99,13 +99,16 @@ const (
CLMUL // Carry-less Multiplication
CLZERO // CLZERO instruction supported
CMOV // i686 CMOV
CMPXCHG8 // CMPXCHG8 instruction
CPBOOST // Core Performance Boost
CX16 // CMPXCHG16B Instruction
ENQCMD // Enqueue Command
ERMS // Enhanced REP MOVSB/STOSB
F16C // Half-precision floating-point conversion
FMA3 // Intel FMA 3. Does not imply AVX.
FMA4 // Bulldozer FMA4 functions
FXSR // FXSAVE, FXRESTOR instructions, CR4 bit 9
FXSROPT // FXSAVE/FXRSTOR optimizations
GFNI // Galois Field New Instructions
HLE // Hardware Lock Elision
HTT // Hyperthreading (enabled)
Expand All @@ -123,23 +126,27 @@ const (
IBSRIPINVALIDCHK // Instruction Based Sampling Feature (AMD)
INT_WBINVD // WBINVD/WBNOINVD are interruptible.
INVLPGB // NVLPGB and TLBSYNC instruction supported
LAHF // LAHF/SAHF in long mode
LZCNT // LZCNT instruction
MCAOVERFLOW // MCA overflow recovery support.
MCOMMIT // MCOMMIT instruction supported
MMX // standard MMX
MMXEXT // SSE integer functions or AMD MMX ext
MOVBE // MOVBE instruction (big-endian)
MOVDIR64B // Move 64 Bytes as Direct Store
MOVDIRI // Move Doubleword as Direct Store
MPX // Intel MPX (Memory Protection Extensions)
MSRIRC // Instruction Retired Counter MSR available
NX // NX (No-Execute) bit
OSXSAVE // XSAVE enabled by OS
POPCNT // POPCNT instruction
RDPRU // RDPRU instruction supported
RDRAND // RDRAND instruction is available
RDSEED // RDSEED instruction is available
RDTSCP // RDTSCP Instruction
RTM // Restricted Transactional Memory
RTM_ALWAYS_ABORT // Indicates that the loaded microcode is forcing RTM abort.
SCE // SYSENTER and SYSEXIT instructions
SERIALIZE // Serialize Instruction Execution
SGX // Software Guard Extensions
SGXLC // Software Guard Extensions Launch Control
Expand All @@ -160,7 +167,9 @@ const (
VPCLMULQDQ // Carry-Less Multiplication Quadword
WAITPKG // TPAUSE, UMONITOR, UMWAIT
WBNOINVD // Write Back and Do Not Invalidate Cache
X87 // FPU
XOP // Bulldozer XOP functions
XSAVE // XSAVE, XRESTOR, XSETBV, XGETBV

// ARM features:
AESARM // AES instructions
Expand Down Expand Up @@ -311,6 +320,31 @@ func (c CPUInfo) Has(id FeatureID) bool {
return c.featureSet.inSet(id)
}

// https://en.wikipedia.org/wiki/X86-64#Microarchitecture_levels
var level1Features = flagSetWith(CMOV, CMPXCHG8, X87, FXSR, MMX, SCE, SSE, SSE2)
var level2Features = flagSetWith(CMOV, CMPXCHG8, X87, FXSR, MMX, SCE, SSE, SSE2, CX16, LAHF, POPCNT, SSE3, SSE4, SSE42, SSSE3)
var level3Features = flagSetWith(CMOV, CMPXCHG8, X87, FXSR, MMX, SCE, SSE, SSE2, CX16, LAHF, POPCNT, SSE3, SSE4, SSE42, SSSE3, AVX, AVX2, BMI1, BMI2, F16C, FMA3, LZCNT, MOVBE, OSXSAVE)
var level4Features = flagSetWith(CMOV, CMPXCHG8, X87, FXSR, MMX, SCE, SSE, SSE2, CX16, LAHF, POPCNT, SSE3, SSE4, SSE42, SSSE3, AVX, AVX2, BMI1, BMI2, F16C, FMA3, LZCNT, MOVBE, OSXSAVE, AVX512F, AVX512BW, AVX512CD, AVX512DQ, AVX512VL)

// X64Level returns the microarchitecture level detected on the CPU.
// If features are lacking or non x64 mode, 0 is returned.
// See https://en.wikipedia.org/wiki/X86-64#Microarchitecture_levels
func (c CPUInfo) X64Level() int {
if c.featureSet.hasSet(level4Features) {
return 4
}
if c.featureSet.hasSet(level3Features) {
return 3
}
if c.featureSet.hasSet(level2Features) {
return 2
}
if c.featureSet.hasSet(level1Features) {
return 1
}
return 0
}

// Disable will disable one or several features.
func (c *CPUInfo) Disable(ids ...FeatureID) bool {
for _, id := range ids {
Expand Down Expand Up @@ -497,6 +531,24 @@ func (s *flagSet) or(other flagSet) {
}
}

// hasSet returns whether all features are present.
func (s flagSet) hasSet(other flagSet) bool {
for i, v := range other[:] {
if s[i]&v != v {
return false
}
}
return true
}

func flagSetWith(feat ...FeatureID) flagSet {
var res flagSet
for _, f := range feat {
res.set(f)
}
return res
}

// ParseFeature will parse the string and return the ID of the matching feature.
// Will return UNKNOWN if not found.
func ParseFeature(s string) FeatureID {
Expand Down Expand Up @@ -706,6 +758,7 @@ func (c *CPUInfo) cacheSize() {
if maxFunctionID() < 4 {
return
}
c.Cache.L1I, c.Cache.L1D, c.Cache.L2, c.Cache.L3 = 0, 0, 0, 0
for i := uint32(0); ; i++ {
eax, ebx, ecx, _ := cpuidex(4, i)
cacheType := eax & 15
Expand Down Expand Up @@ -861,9 +914,14 @@ func support() flagSet {
family, model := familyModel()

_, _, c, d := cpuid(1)
fs.setIf((d&(1<<0)) != 0, X87)
fs.setIf((d&(1<<8)) != 0, CMPXCHG8)
fs.setIf((d&(1<<11)) != 0, SCE)
fs.setIf((d&(1<<15)) != 0, CMOV)
fs.setIf((d&(1<<22)) != 0, MMXEXT)
fs.setIf((d&(1<<23)) != 0, MMX)
fs.setIf((d&(1<<25)) != 0, MMXEXT)
fs.setIf((d&(1<<24)) != 0, FXSR)
fs.setIf((d&(1<<25)) != 0, FXSROPT)
fs.setIf((d&(1<<25)) != 0, SSE)
fs.setIf((d&(1<<26)) != 0, SSE2)
fs.setIf((c&1) != 0, SSE3)
Expand All @@ -873,6 +931,7 @@ func support() flagSet {
fs.setIf((c&0x00100000) != 0, SSE42)
fs.setIf((c&(1<<25)) != 0, AESNI)
fs.setIf((c&(1<<1)) != 0, CLMUL)
fs.setIf(c&(1<<22) != 0, MOVBE)
fs.setIf(c&(1<<23) != 0, POPCNT)
fs.setIf(c&(1<<30) != 0, RDRAND)

Expand All @@ -888,6 +947,8 @@ func support() flagSet {
if vend == AMD && (d&(1<<28)) != 0 && mfi >= 4 {
fs.setIf(threadsPerCore() > 1, HTT)
}
fs.setIf(c&1<<26 != 0, XSAVE)
fs.setIf(c&1<<27 != 0, OSXSAVE)
// Check XGETBV/XSAVE (26), OXSAVE (27) and AVX (28) bits
const avxCheck = 1<<26 | 1<<27 | 1<<28
if c&avxCheck == avxCheck {
Expand Down Expand Up @@ -992,6 +1053,7 @@ func support() flagSet {
fs.set(LZCNT)
fs.set(POPCNT)
}
fs.setIf((c&(1<<0)) != 0, LAHF)
fs.setIf((c&(1<<10)) != 0, IBS)
fs.setIf((d&(1<<31)) != 0, AMD3DNOW)
fs.setIf((d&(1<<30)) != 0, AMD3DNOWEXT)
Expand Down
187 changes: 98 additions & 89 deletions featureid_string.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions mockcpu_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -187,6 +187,7 @@ func TestMocks(t *testing.T) {
t.Log("LogicalCores:", CPU.LogicalCores)
t.Log("Family", CPU.Family, "Model:", CPU.Model)
t.Log("Features:", strings.Join(CPU.FeatureSet(), ","))
t.Log("Microarchitecture level:", CPU.X64Level())
t.Log("Cacheline bytes:", CPU.CacheLine)
t.Log("L1 Instruction Cache:", CPU.Cache.L1I, "bytes")
t.Log("L1 Data Cache:", CPU.Cache.L1D, "bytes")
Expand Down
5 changes: 4 additions & 1 deletion testdata/getall.go
Original file line number Diff line number Diff line change
@@ -1,14 +1,17 @@
//go:build ignore

package main

import (
"archive/zip"
_ "bytes"
"fmt"
"golang.org/x/net/html"
"io"
"net/http"
"os"
"strings"

"golang.org/x/net/html"
)

// Download all CPUID dumps from http://users.atw.hu/instlatx64/
Expand Down

0 comments on commit eb76847

Please sign in to comment.