Skip to content

Commit 2a5efe8

Browse files
authored
Fix AMD cache hang on buggy Xen hypervisor (#104)
Xen Hypervisor is buggy and returns the same entry no matter ECX value. Hack: When we encounter the same entry 100 times we break. Fixes #103
1 parent 63ef1e5 commit 2a5efe8

1 file changed

Lines changed: 26 additions & 1 deletion

File tree

cpuid.go

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -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.
392394
func (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+
566576
func 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

Comments
 (0)