@@ -14,6 +14,7 @@ import (
1414 "flag"
1515 "fmt"
1616 "math"
17+ "math/bits"
1718 "os"
1819 "runtime"
1920 "strings"
@@ -389,8 +390,9 @@ func (c CPUInfo) IsVendor(v Vendor) bool {
389390 return c .VendorID == v
390391}
391392
393+ // FeatureSet returns all available features as strings.
392394func (c CPUInfo ) FeatureSet () []string {
393- s := make ([]string , 0 )
395+ s := make ([]string , 0 , c . featureSet . nEnabled () )
394396 s = append (s , c .featureSet .Strings ()... )
395397 return s
396398}
@@ -563,6 +565,14 @@ func (s flagSet) hasSet(other flagSet) bool {
563565 return true
564566}
565567
568+ // nEnabled will return the number of enabled flags.
569+ func (s flagSet ) nEnabled () (n int ) {
570+ for _ , v := range s [:] {
571+ n += bits .OnesCount64 (uint64 (v ))
572+ }
573+ return n
574+ }
575+
566576func flagSetWith (feat ... FeatureID ) flagSet {
567577 var res flagSet
568578 for _ , f := range feat {
@@ -834,6 +844,11 @@ func (c *CPUInfo) cacheSize() {
834844 if maxExtendedFunction () < 0x8000001D {
835845 return
836846 }
847+
848+ // Xen Hypervisor is buggy and returns the same entry no matter ECX value.
849+ // Hack: When we encounter the same entry 100 times we break.
850+ nSame := 0
851+ var last uint32
837852 for i := uint32 (0 ); i < math .MaxUint32 ; i ++ {
838853 eax , ebx , ecx , _ := cpuidex (0x8000001D , i )
839854
@@ -849,6 +864,16 @@ func (c *CPUInfo) cacheSize() {
849864 return
850865 }
851866
867+ // Check for the same value repeated.
868+ comb := eax ^ ebx ^ ecx
869+ if comb == last {
870+ nSame ++
871+ if nSame == 100 {
872+ return
873+ }
874+ }
875+ last = comb
876+
852877 switch level {
853878 case 1 :
854879 switch typ {
0 commit comments