Skip to content

Commit

Permalink
Fix AMD cache hang on buggy Xen hypervisor (#104)
Browse files Browse the repository at this point in the history
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
  • Loading branch information
klauspost committed Jun 21, 2022
1 parent 63ef1e5 commit 2a5efe8
Showing 1 changed file with 26 additions and 1 deletion.
27 changes: 26 additions & 1 deletion cpuid.go
Expand Up @@ -14,6 +14,7 @@ import (
"flag"
"fmt"
"math"
"math/bits"
"os"
"runtime"
"strings"
Expand Down Expand Up @@ -389,8 +390,9 @@ func (c CPUInfo) IsVendor(v Vendor) bool {
return c.VendorID == v
}

// FeatureSet returns all available features as strings.
func (c CPUInfo) FeatureSet() []string {
s := make([]string, 0)
s := make([]string, 0, c.featureSet.nEnabled())
s = append(s, c.featureSet.Strings()...)
return s
}
Expand Down Expand Up @@ -563,6 +565,14 @@ func (s flagSet) hasSet(other flagSet) bool {
return true
}

// nEnabled will return the number of enabled flags.
func (s flagSet) nEnabled() (n int) {
for _, v := range s[:] {
n += bits.OnesCount64(uint64(v))
}
return n
}

func flagSetWith(feat ...FeatureID) flagSet {
var res flagSet
for _, f := range feat {
Expand Down Expand Up @@ -834,6 +844,11 @@ func (c *CPUInfo) cacheSize() {
if maxExtendedFunction() < 0x8000001D {
return
}

// Xen Hypervisor is buggy and returns the same entry no matter ECX value.
// Hack: When we encounter the same entry 100 times we break.
nSame := 0
var last uint32
for i := uint32(0); i < math.MaxUint32; i++ {
eax, ebx, ecx, _ := cpuidex(0x8000001D, i)

Expand All @@ -849,6 +864,16 @@ func (c *CPUInfo) cacheSize() {
return
}

// Check for the same value repeated.
comb := eax ^ ebx ^ ecx
if comb == last {
nSame++
if nSame == 100 {
return
}
}
last = comb

switch level {
case 1:
switch typ {
Expand Down

0 comments on commit 2a5efe8

Please sign in to comment.