@@ -2,6 +2,7 @@ package analyzer
22
33import (
44 "encoding/json"
5+ "slices"
56 "strconv"
67 "strings"
78
@@ -10,6 +11,18 @@ import (
1011 "github.com/replicatedhq/troubleshoot/pkg/collect"
1112)
1213
14+ // microarchs holds a list of features present in each microarchitecture.
15+ // ref: https://gitlab.com/x86-psABIs/x86-64-ABI
16+ // ref: https://developers.redhat.com/blog/2021/01/05/building-red-hat-enterprise-linux-9-for-the-x86-64-v2-microarchitecture-level
17+ var microarchs = map [string ][]string {
18+ "x86-64-v2" : {"cx16" , "lahf_lm" , "popcnt" , "ssse3" , "sse4_1" , "sse4_2" , "ssse3" },
19+ "x86-64-v3" : {"avx" , "avx2" , "bmi1" , "bmi2" , "f16c" , "fma" , "lzcnt" , "movbe" , "xsave" },
20+ "x86-64-v4" : {"avx512f" , "avx512bw" , "avx512cd" , "avx512dq" , "avx512vl" },
21+ }
22+
23+ // x8664BaseFeatures are the features that are present in all x86-64 microarchitectures.
24+ var x8664BaseFeatures = []string {"cmov" , "cx8" , "fpu" , "fxsr" , "mmx" , "syscall" , "sse" , "sse2" }
25+
1326type AnalyzeHostCPU struct {
1427 hostAnalyzer * troubleshootv1beta2.CPUAnalyze
1528}
@@ -52,7 +65,7 @@ func (a *AnalyzeHostCPU) Analyze(
5265 return []* AnalyzeResult {& result }, nil
5366 }
5467
55- isMatch , err := compareHostCPUConditionalToActual (outcome .Fail .When , cpuInfo .LogicalCount , cpuInfo .PhysicalCount )
68+ isMatch , err := compareHostCPUConditionalToActual (outcome .Fail .When , cpuInfo .LogicalCount , cpuInfo .PhysicalCount , cpuInfo . Flags )
5669 if err != nil {
5770 return nil , errors .Wrap (err , "failed to compare" )
5871 }
@@ -73,7 +86,7 @@ func (a *AnalyzeHostCPU) Analyze(
7386 return []* AnalyzeResult {& result }, nil
7487 }
7588
76- isMatch , err := compareHostCPUConditionalToActual (outcome .Warn .When , cpuInfo .LogicalCount , cpuInfo .PhysicalCount )
89+ isMatch , err := compareHostCPUConditionalToActual (outcome .Warn .When , cpuInfo .LogicalCount , cpuInfo .PhysicalCount , cpuInfo . Flags )
7790 if err != nil {
7891 return nil , errors .Wrap (err , "failed to compare" )
7992 }
@@ -94,7 +107,7 @@ func (a *AnalyzeHostCPU) Analyze(
94107 return []* AnalyzeResult {& result }, nil
95108 }
96109
97- isMatch , err := compareHostCPUConditionalToActual (outcome .Pass .When , cpuInfo .LogicalCount , cpuInfo .PhysicalCount )
110+ isMatch , err := compareHostCPUConditionalToActual (outcome .Pass .When , cpuInfo .LogicalCount , cpuInfo .PhysicalCount , cpuInfo . Flags )
98111 if err != nil {
99112 return nil , errors .Wrap (err , "failed to compare" )
100113 }
@@ -112,7 +125,25 @@ func (a *AnalyzeHostCPU) Analyze(
112125 return []* AnalyzeResult {& result }, nil
113126}
114127
115- func compareHostCPUConditionalToActual (conditional string , logicalCount int , physicalCount int ) (res bool , err error ) {
128+ func doCompareHostCPUMicroArchitecture (microarch string , flags []string ) (res bool , err error ) {
129+ specifics , ok := microarchs [microarch ]
130+ if ! ok && microarch != "x86-64" {
131+ return false , errors .Errorf ("troubleshoot does not yet support microarchitecture %q" , microarch )
132+ }
133+ expectedFlags := x8664BaseFeatures
134+ if len (specifics ) > 0 {
135+ expectedFlags = append (expectedFlags , specifics ... )
136+ }
137+ for _ , flag := range expectedFlags {
138+ if slices .Contains (flags , flag ) {
139+ continue
140+ }
141+ return false , nil
142+ }
143+ return true , nil
144+ }
145+
146+ func compareHostCPUConditionalToActual (conditional string , logicalCount int , physicalCount int , flags []string ) (res bool , err error ) {
116147 compareLogical := false
117148 comparePhysical := false
118149 compareUnspecified := false
@@ -137,6 +168,11 @@ func compareHostCPUConditionalToActual(conditional string, logicalCount int, phy
137168 desired = parts [1 ]
138169 }
139170
171+ // analyze if the cpu supports a specific set of features, aka as micrarchitecture.
172+ if strings .ToLower (comparator ) == "supports" {
173+ return doCompareHostCPUMicroArchitecture (desired , flags )
174+ }
175+
140176 if ! compareLogical && ! comparePhysical && ! compareUnspecified {
141177 return false , errors .New ("unable to parse conditional" )
142178 }
0 commit comments