Update
This commit is contained in:
1 parent
3530afb854
commit
6903fcff27
2146 files changed
+112256
-190703
No files matched your search
+4
-3
@@ -233,9 +233,10 @@ func readHWCap(auxvFilepath string) (hwCap, error) {
|
||||
for i := 0; i < l; i++ {
|
||||
tag := binary.LittleEndian.Uint64(auxv[i*16:])
|
||||
val := binary.LittleEndian.Uint64(auxv[i*16+8:])
|
||||
if tag == _AT_HWCAP {
|
||||
switch tag {
|
||||
case _AT_HWCAP:
|
||||
c.hwCap1 = val
|
||||
} else if tag == _AT_HWCAP2 {
|
||||
case _AT_HWCAP2:
|
||||
c.hwCap2 = val
|
||||
}
|
||||
|
||||
@@ -249,7 +250,7 @@ func readHWCap(auxvFilepath string) (hwCap, error) {
|
||||
func initHWCap() {
|
||||
c, err := readHWCap("/proc/self/auxv")
|
||||
if err != nil {
|
||||
log.Warningf("cpuid HWCap not initialized: %w", err)
|
||||
log.Warningf("cpuid HWCap not initialized: %v", err)
|
||||
} else {
|
||||
hostFeatureSet.hwCap = c
|
||||
}
|
||||
|
||||
+46
-13
@@ -192,7 +192,24 @@ func (fs FeatureSet) VirtualAddressBits() uint32 {
|
||||
//go:nosplit
|
||||
func (fs FeatureSet) PhysicalAddressBits() uint32 {
|
||||
ax, _, _, _ := fs.query(addressSizes)
|
||||
return ax & 0xff
|
||||
physBits := ax & 0xff
|
||||
if !fs.AMD() {
|
||||
return physBits
|
||||
}
|
||||
|
||||
maxExtended, _, _, _ := fs.query(extendedFunctionInfo)
|
||||
if maxExtended < uint32(amdMemoryEncryptionInfo) {
|
||||
return physBits
|
||||
}
|
||||
|
||||
memEncAX, memEncBX, _, _ := fs.query(amdMemoryEncryptionInfo)
|
||||
if memEncAX&amdMemoryEncryptionFeatureMask == 0 {
|
||||
return physBits
|
||||
}
|
||||
// AMD memory encryption reduces usable physical address width by the
|
||||
// CPUID-reported amount. Match Linux's
|
||||
// arch/x86/kernel/cpu/amd.c:early_detect_mem_encrypt().
|
||||
return physBits - ((memEncBX >> amdPhysAddrReductionShift) & amdPhysAddrReductionMask)
|
||||
}
|
||||
|
||||
// CacheType describes the type of a cache, as returned in eax[4:0] for eax=4.
|
||||
@@ -306,6 +323,19 @@ func (fs FeatureSet) HasFeature(feature Feature) bool {
|
||||
return feature.check(fs)
|
||||
}
|
||||
|
||||
// x86Family returns the CPU family printed in /proc/cpuinfo from a CPUID
|
||||
// leaf 1 EAX signature.
|
||||
//
|
||||
// This matches Linux arch/x86/lib/cpu.c:x86_family(). When the 4-bit
|
||||
// family ID is 0xf, the 8-bit extended family is added.
|
||||
func x86Family(sig uint32) uint32 {
|
||||
family := (sig >> 8) & 0xf
|
||||
if family == 0xf {
|
||||
family += (sig >> 20) & 0xff
|
||||
}
|
||||
return family
|
||||
}
|
||||
|
||||
// WriteCPUInfoTo is to generate a section of one cpu in /proc/cpuinfo. This is
|
||||
// a minimal /proc/cpuinfo, it is missing some fields like "microcode" that are
|
||||
// not always printed in Linux. Several fields are simply made up.
|
||||
@@ -313,11 +343,11 @@ func (fs FeatureSet) WriteCPUInfoTo(cpu, numCPU uint, w io.Writer) {
|
||||
// Avoid many redundant calls here, since this can occasionally appear
|
||||
// in the hot path. Read all basic information up front, see above.
|
||||
ax, _, _, _ := fs.query(featureInfo)
|
||||
ef, em, _, f, m, _ := signatureSplit(ax)
|
||||
_, em, _, _, m, _ := signatureSplit(ax)
|
||||
vendor := fs.VendorID()
|
||||
fmt.Fprintf(w, "processor\t: %d\n", cpu)
|
||||
fmt.Fprintf(w, "vendor_id\t: %s\n", string(vendor[:]))
|
||||
fmt.Fprintf(w, "cpu family\t: %d\n", ((ef<<4)&0xff)|f)
|
||||
fmt.Fprintf(w, "cpu family\t: %d\n", x86Family(ax))
|
||||
fmt.Fprintf(w, "model\t\t: %d\n", ((em<<4)&0xff)|m)
|
||||
fmt.Fprintf(w, "model name\t: %s\n", "unknown") // Unknown for now.
|
||||
fmt.Fprintf(w, "stepping\t: %s\n", "unknown") // Unknown for now.
|
||||
@@ -382,15 +412,16 @@ var (
|
||||
)
|
||||
|
||||
const (
|
||||
// XCR0AMXMask are the bits that enable xsave to operate on AMX TILECFG
|
||||
// and TILEDATA.
|
||||
//
|
||||
// Note: TILECFG and TILEDATA are always either both enabled or both
|
||||
// disabled.
|
||||
// XCR0AmxCfgMask is the bits that enable xsave to operate on
|
||||
// AMX TILECFG.
|
||||
//
|
||||
// See Intel® 64 and IA-32 Architectures Software Developer’s Manual Vol.1
|
||||
// section 13.3 for details.
|
||||
XCR0AMXMask = uint64((1 << 17) | (1 << 18))
|
||||
XCR0AmxCfgMask = uint64(1 << 17)
|
||||
|
||||
// XCR0AmxDataMask is the bits that enable xsave to operate on
|
||||
// AMX TILEDATA.
|
||||
XCR0AmxDataMask = uint64(1 << 18)
|
||||
)
|
||||
|
||||
// ExtendedStateSize returns the number of bytes needed to save the "extended
|
||||
@@ -415,13 +446,15 @@ func (fs FeatureSet) ExtendedStateSize() (size, align uint) {
|
||||
// AMXExtendedStateSize returns the number of bytes within the "extended state"
|
||||
// area that is used for AMX.
|
||||
func (fs FeatureSet) AMXExtendedStateSize() uint {
|
||||
total := uint(0)
|
||||
if fs.UseXsave() {
|
||||
xcr0 := xgetbv(0)
|
||||
if (xcr0 & XCR0AMXMask) != 0 {
|
||||
return uint(amxTileCfgSize + amxTileDataSize)
|
||||
// TILECFG is not part of AMX extended state, only TILEDATA.
|
||||
if (xcr0 & XCR0AmxDataMask) != 0 {
|
||||
total += uint(amxTileDataSize)
|
||||
}
|
||||
}
|
||||
return 0
|
||||
return total
|
||||
}
|
||||
|
||||
// ValidXCR0Mask returns the valid bits in control register XCR0.
|
||||
@@ -435,7 +468,7 @@ func (fs FeatureSet) ValidXCR0Mask() uint64 {
|
||||
return 0
|
||||
}
|
||||
ax, _, _, dx := fs.query(xSaveInfo)
|
||||
return (uint64(dx)<<32 | uint64(ax)) &^ XCR0AMXMask
|
||||
return (uint64(dx)<<32 | uint64(ax)) &^ (XCR0AmxCfgMask | XCR0AmxDataMask)
|
||||
}
|
||||
|
||||
// UseXsave returns the choice of fp state saving instruction.
|
||||
|
||||
@@ -27,8 +27,8 @@ func (fs *FeatureSet) beforeSave() {}
|
||||
// +checklocksignore
|
||||
func (fs *FeatureSet) StateSave(stateSinkObject state.Sink) {
|
||||
fs.beforeSave()
|
||||
var FunctionValue Static
|
||||
FunctionValue = fs.saveFunction()
|
||||
FunctionValue := fs.saveFunction()
|
||||
_ = (Static)(FunctionValue)
|
||||
stateSinkObject.SaveValue(0, FunctionValue)
|
||||
stateSinkObject.Save(1, &fs.hwCap)
|
||||
}
|
||||
|
||||
+46
-18
@@ -63,15 +63,25 @@ const xSaveInfoNumLeaves = 64 // Maximum number of xSaveInfo leaves.
|
||||
|
||||
// The "extended" functions.
|
||||
const (
|
||||
extendedStart cpuidFunction = 0x80000000
|
||||
extendedFunctionInfo cpuidFunction = extendedStart + 0 // Returns highest available extended function in eax.
|
||||
extendedFeatures = extendedStart + 1 // Returns some extended feature bits in edx and ecx.
|
||||
processorBrandString2 = extendedStart + 2 // Processor Name String Identifier.
|
||||
processorBrandString3 = extendedStart + 3 // Processor Name String Identifier.
|
||||
processorBrandString4 = extendedStart + 4 // Processor Name String Identifier.
|
||||
l1CacheAndTLBInfo = extendedStart + 5 // Returns L2 cache information.
|
||||
l2CacheInfo = extendedStart + 6 // Returns L2 cache information.
|
||||
addressSizes = extendedStart + 8 // Physical and virtual address sizes.
|
||||
extendedStart cpuidFunction = 0x80000000
|
||||
extendedFunctionInfo cpuidFunction = extendedStart + 0 // Returns highest available extended function in eax.
|
||||
extendedFeatures = extendedStart + 1 // Returns some extended feature bits in edx and ecx.
|
||||
processorBrandString2 = extendedStart + 2 // Processor Name String Identifier.
|
||||
processorBrandString3 = extendedStart + 3 // Processor Name String Identifier.
|
||||
processorBrandString4 = extendedStart + 4 // Processor Name String Identifier.
|
||||
l1CacheAndTLBInfo = extendedStart + 5 // Returns L2 cache information.
|
||||
l2CacheInfo = extendedStart + 6 // Returns L2 cache information.
|
||||
addressSizes = extendedStart + 8 // Physical and virtual address sizes.
|
||||
amdMemoryEncryptionInfo = extendedStart + 31 // AMD memory encryption information.
|
||||
)
|
||||
|
||||
// AMD-defined memory encryption feature bits and fields.
|
||||
const (
|
||||
amdSecureMemoryEncryption = 1 << 0
|
||||
amdSecureEncryptedVirtualization = 1 << 1
|
||||
amdMemoryEncryptionFeatureMask = amdSecureMemoryEncryption | amdSecureEncryptedVirtualization
|
||||
amdPhysAddrReductionShift = 6
|
||||
amdPhysAddrReductionMask = 0x3f
|
||||
)
|
||||
|
||||
var allowedBasicFunctions = [...]bool{
|
||||
@@ -84,14 +94,15 @@ var allowedBasicFunctions = [...]bool{
|
||||
}
|
||||
|
||||
var allowedExtendedFunctions = [...]bool{
|
||||
extendedFunctionInfo - extendedStart: true,
|
||||
extendedFeatures - extendedStart: true,
|
||||
addressSizes - extendedStart: true,
|
||||
processorBrandString2 - extendedStart: true,
|
||||
processorBrandString3 - extendedStart: true,
|
||||
processorBrandString4 - extendedStart: true,
|
||||
l1CacheAndTLBInfo - extendedStart: true,
|
||||
l2CacheInfo - extendedStart: true,
|
||||
extendedFunctionInfo - extendedStart: true,
|
||||
extendedFeatures - extendedStart: true,
|
||||
addressSizes - extendedStart: true,
|
||||
processorBrandString2 - extendedStart: true,
|
||||
processorBrandString3 - extendedStart: true,
|
||||
processorBrandString4 - extendedStart: true,
|
||||
l1CacheAndTLBInfo - extendedStart: true,
|
||||
l2CacheInfo - extendedStart: true,
|
||||
amdMemoryEncryptionInfo - extendedStart: true,
|
||||
}
|
||||
|
||||
// Function executes a CPUID function.
|
||||
@@ -119,7 +130,7 @@ func (i *In) normalize() {
|
||||
switch cpuidFunction(i.Eax) {
|
||||
case vendorID, featureInfo, intelCacheDescriptors, extendedFunctionInfo, extendedFeatures:
|
||||
i.Ecx = 0 // Ignore.
|
||||
case processorBrandString2, processorBrandString3, processorBrandString4, l1CacheAndTLBInfo, l2CacheInfo:
|
||||
case processorBrandString2, processorBrandString3, processorBrandString4, l1CacheAndTLBInfo, l2CacheInfo, amdMemoryEncryptionInfo:
|
||||
i.Ecx = 0 // Ignore.
|
||||
case intelDeterministicCacheParams, extendedFeatureInfo:
|
||||
// Preserve i.Ecx.
|
||||
@@ -163,6 +174,23 @@ func (fs FeatureSet) query(fn cpuidFunction) (uint32, uint32, uint32, uint32) {
|
||||
return out.Eax, out.Ebx, out.Ecx, out.Edx
|
||||
}
|
||||
|
||||
// Intersect returns the intersection of features between self and allowedFeatures.
|
||||
func (fs FeatureSet) Intersect(allowedFeatures map[Feature]struct{}) (FeatureSet, error) {
|
||||
hs := fs.ToStatic()
|
||||
|
||||
// only keep features inside allowedFeatures.
|
||||
for f := range allFeatures {
|
||||
if fs.HasFeature(f) {
|
||||
if _, ok := allowedFeatures[f]; !ok {
|
||||
log.Infof("Removing CPU feature %v as it is not allowed.", f)
|
||||
hs.Remove(f)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return hs.ToFeatureSet(), nil
|
||||
}
|
||||
|
||||
var hostFeatureSet FeatureSet
|
||||
|
||||
// HostFeatureSet returns a host CPUID.
|
||||
|
||||
@@ -18,6 +18,7 @@
|
||||
package cpuid
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"runtime"
|
||||
"strconv"
|
||||
@@ -41,6 +42,13 @@ func (fs FeatureSet) Fixed() FeatureSet {
|
||||
return fs
|
||||
}
|
||||
|
||||
// Intersect returns the intersection of features between self and allowedFeatures.
|
||||
//
|
||||
// Just return error as there is no ARM64 equivalent to cpuid.Static.Remove().
|
||||
func (fs FeatureSet) Intersect(allowedFeatures map[Feature]struct{}) (FeatureSet, error) {
|
||||
return FeatureSet{}, fmt.Errorf("FeatureSet intersection is not supported on ARM64")
|
||||
}
|
||||
|
||||
// Reads CPU information from host /proc/cpuinfo.
|
||||
//
|
||||
// Must run before syscall filter installation. This value is used to create
|
||||
|
||||
+2
-2
@@ -105,8 +105,8 @@ func (s Static) normalize() {
|
||||
if fs.HasFeature(X86FeatureXSAVE) {
|
||||
in := In{Eax: uint32(xSaveInfo)}
|
||||
out := s[in]
|
||||
out.Ecx = maxXsaveSize
|
||||
out.Ebx = xsaveSize
|
||||
out.Ecx = max(out.Ecx, maxXsaveSize)
|
||||
out.Ebx = max(out.Ebx, xsaveSize)
|
||||
s[in] = out
|
||||
}
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user