Update dependencies
This commit is contained in:
264
vendor/gvisor.dev/gvisor/pkg/cpuid/cpuid.go
vendored
Normal file
264
vendor/gvisor.dev/gvisor/pkg/cpuid/cpuid.go
vendored
Normal file
@@ -0,0 +1,264 @@
|
||||
// Copyright 2019 The gVisor Authors.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
// Package cpuid provides basic functionality for creating and adjusting CPU
|
||||
// feature sets.
|
||||
//
|
||||
// Each architecture should define its own FeatureSet type, that must be
|
||||
// savable, along with an allFeatures map, appropriate arch hooks and a
|
||||
// HostFeatureSet function. This file contains common functionality to all
|
||||
// architectures, which is essentially string munging and some errors.
|
||||
//
|
||||
// Individual architectures may export methods on FeatureSet that are relevant,
|
||||
// e.g. FeatureSet.Vendor(). Common to all architectures, FeatureSets include
|
||||
// HasFeature, which provides a trivial mechanism to test for the presence of
|
||||
// specific hardware features. The hardware features are also defined on a
|
||||
// per-architecture basis.
|
||||
package cpuid
|
||||
|
||||
import (
|
||||
"encoding/binary"
|
||||
"fmt"
|
||||
"os"
|
||||
"runtime"
|
||||
"strings"
|
||||
|
||||
"gvisor.dev/gvisor/pkg/log"
|
||||
"gvisor.dev/gvisor/pkg/sync"
|
||||
)
|
||||
|
||||
// contextID is the package for anyContext.Context.Value keys.
|
||||
type contextID int
|
||||
|
||||
const (
|
||||
// CtxFeatureSet is the FeatureSet for the context.
|
||||
CtxFeatureSet contextID = iota
|
||||
|
||||
// hardware capability bit vector.
|
||||
_AT_HWCAP = 16
|
||||
// hardware capability bit vector 2.
|
||||
_AT_HWCAP2 = 26
|
||||
)
|
||||
|
||||
// anyContext represents context.Context.
|
||||
type anyContext interface {
|
||||
Value(key any) any
|
||||
}
|
||||
|
||||
// FromContext returns the FeatureSet from the context, if available.
|
||||
func FromContext(ctx anyContext) FeatureSet {
|
||||
v := ctx.Value(CtxFeatureSet)
|
||||
if v == nil {
|
||||
return FeatureSet{} // Panics if used.
|
||||
}
|
||||
return v.(FeatureSet)
|
||||
}
|
||||
|
||||
// Feature is a unique identifier for a particular cpu feature. We just use an
|
||||
// int as a feature number on x86 and arm64.
|
||||
//
|
||||
// On x86, features are numbered according to "blocks". Each block is 32 bits, and
|
||||
// feature bits from the same source (cpuid leaf/level) are in the same block.
|
||||
//
|
||||
// On arm64, features are numbered according to the ELF HWCAP definition, from
|
||||
// arch/arm64/include/uapi/asm/hwcap.h.
|
||||
type Feature int
|
||||
|
||||
// allFeatureInfo is the value for allFeatures.
|
||||
type allFeatureInfo struct {
|
||||
// displayName is the short display name for the feature.
|
||||
displayName string
|
||||
|
||||
// shouldAppear indicates whether the feature normally appears in
|
||||
// cpuinfo. This affects FlagString only.
|
||||
shouldAppear bool
|
||||
}
|
||||
|
||||
// String implements fmt.Stringer.String.
|
||||
func (f Feature) String() string {
|
||||
info, ok := allFeatures[f]
|
||||
if ok {
|
||||
return info.displayName
|
||||
}
|
||||
return fmt.Sprintf("[0x%x?]", int(f)) // No given name.
|
||||
}
|
||||
|
||||
// reverseMap is a map from displayName to Feature.
|
||||
var reverseMap = func() map[string]Feature {
|
||||
m := make(map[string]Feature)
|
||||
for feature, info := range allFeatures {
|
||||
if info.displayName != "" {
|
||||
// Sanity check that the name is unique.
|
||||
if old, ok := m[info.displayName]; ok {
|
||||
panic(fmt.Sprintf("feature %v has conflicting values (0x%x vs 0x%x)", info.displayName, old, feature))
|
||||
}
|
||||
m[info.displayName] = feature
|
||||
}
|
||||
}
|
||||
return m
|
||||
}()
|
||||
|
||||
// FeatureFromString returns the Feature associated with the given feature
|
||||
// string plus a bool to indicate if it could find the feature.
|
||||
func FeatureFromString(s string) (Feature, bool) {
|
||||
feature, ok := reverseMap[s]
|
||||
return feature, ok
|
||||
}
|
||||
|
||||
// AllFeatures returns the full set of all possible features.
|
||||
func AllFeatures() (features []Feature) {
|
||||
archFlagOrder(func(f Feature) {
|
||||
features = append(features, f)
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
// Subtract returns the features present in fs that are not present in other.
|
||||
// If all features in fs are present in other, Subtract returns nil.
|
||||
//
|
||||
// This does not check for any kinds of incompatibility.
|
||||
func (fs FeatureSet) Subtract(other FeatureSet) (left map[Feature]struct{}) {
|
||||
for feature := range allFeatures {
|
||||
thisHas := fs.HasFeature(feature)
|
||||
otherHas := other.HasFeature(feature)
|
||||
if thisHas && !otherHas {
|
||||
if left == nil {
|
||||
left = make(map[Feature]struct{})
|
||||
}
|
||||
left[feature] = struct{}{}
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// FlagString prints out supported CPU flags.
|
||||
func (fs FeatureSet) FlagString() string {
|
||||
var s []string
|
||||
archFlagOrder(func(feature Feature) {
|
||||
if !fs.HasFeature(feature) {
|
||||
return
|
||||
}
|
||||
info := allFeatures[feature]
|
||||
if !info.shouldAppear {
|
||||
return
|
||||
}
|
||||
s = append(s, info.displayName)
|
||||
})
|
||||
return strings.Join(s, " ")
|
||||
}
|
||||
|
||||
// ErrIncompatible is returned for incompatible feature sets.
|
||||
type ErrIncompatible struct {
|
||||
reason string
|
||||
}
|
||||
|
||||
// Error implements error.Error.
|
||||
func (e *ErrIncompatible) Error() string {
|
||||
return fmt.Sprintf("incompatible FeatureSet: %v", e.reason)
|
||||
}
|
||||
|
||||
// CheckHostCompatible returns nil if fs is a subset of the host feature set.
|
||||
func (fs FeatureSet) CheckHostCompatible() error {
|
||||
hfs := HostFeatureSet()
|
||||
|
||||
// Check that hfs is a superset of fs.
|
||||
if diff := fs.Subtract(hfs); len(diff) > 0 {
|
||||
return &ErrIncompatible{
|
||||
reason: fmt.Sprintf("missing features: %v", diff),
|
||||
}
|
||||
}
|
||||
|
||||
// Make arch-specific checks.
|
||||
return fs.archCheckHostCompatible(hfs)
|
||||
}
|
||||
|
||||
// +stateify savable
|
||||
type hwCap struct {
|
||||
// hwCap1 stores HWCAP bits exposed through the elf auxiliary vector.
|
||||
hwCap1 uint64
|
||||
// hwCap2 stores HWCAP2 bits exposed through the elf auxiliary vector.
|
||||
hwCap2 uint64
|
||||
}
|
||||
|
||||
// The auxiliary vector of a process on the Linux system can be read
|
||||
// from /proc/self/auxv, and tags and values are stored as 8-bytes
|
||||
// decimal key-value pairs on the 64-bit system.
|
||||
//
|
||||
// $ od -t d8 /proc/self/auxv
|
||||
//
|
||||
// 0000000 33 140734615224320
|
||||
// 0000020 16 3219913727
|
||||
// 0000040 6 4096
|
||||
// 0000060 17 100
|
||||
// 0000100 3 94665627353152
|
||||
// 0000120 4 56
|
||||
// 0000140 5 9
|
||||
// 0000160 7 140425502162944
|
||||
// 0000200 8 0
|
||||
// 0000220 9 94665627365760
|
||||
// 0000240 11 1000
|
||||
// 0000260 12 1000
|
||||
// 0000300 13 1000
|
||||
// 0000320 14 1000
|
||||
// 0000340 23 0
|
||||
// 0000360 25 140734614619513
|
||||
// 0000400 26 0
|
||||
// 0000420 31 140734614626284
|
||||
// 0000440 15 140734614619529
|
||||
// 0000460 0 0
|
||||
func readHWCap(auxvFilepath string) (hwCap, error) {
|
||||
c := hwCap{}
|
||||
if runtime.GOOS != "linux" {
|
||||
// Don't try to read Linux-specific /proc files.
|
||||
return c, fmt.Errorf("readHwCap only supported on linux, not %s", runtime.GOOS)
|
||||
}
|
||||
|
||||
auxv, err := os.ReadFile(auxvFilepath)
|
||||
if err != nil {
|
||||
return c, fmt.Errorf("failed to read file %s: %w", auxvFilepath, err)
|
||||
}
|
||||
|
||||
l := len(auxv) / 16
|
||||
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 {
|
||||
c.hwCap1 = val
|
||||
} else if tag == _AT_HWCAP2 {
|
||||
c.hwCap2 = val
|
||||
}
|
||||
|
||||
if (c.hwCap1 != 0) && (c.hwCap2 != 0) {
|
||||
break
|
||||
}
|
||||
}
|
||||
return c, nil
|
||||
}
|
||||
|
||||
func initHWCap() {
|
||||
c, err := readHWCap("/proc/self/auxv")
|
||||
if err != nil {
|
||||
log.Warningf("cpuid HWCap not initialized: %w", err)
|
||||
} else {
|
||||
hostFeatureSet.hwCap = c
|
||||
}
|
||||
}
|
||||
|
||||
var initOnce sync.Once
|
||||
|
||||
// Initialize initializes the global data structures used by this package.
|
||||
// Must be called prior to using anything else in this package.
|
||||
func Initialize() {
|
||||
initOnce.Do(archInitialize)
|
||||
}
|
||||
475
vendor/gvisor.dev/gvisor/pkg/cpuid/cpuid_amd64.go
vendored
Normal file
475
vendor/gvisor.dev/gvisor/pkg/cpuid/cpuid_amd64.go
vendored
Normal file
@@ -0,0 +1,475 @@
|
||||
// Copyright 2019 The gVisor Authors.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
//go:build amd64
|
||||
// +build amd64
|
||||
|
||||
package cpuid
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"io"
|
||||
)
|
||||
|
||||
// FeatureSet defines features in terms of CPUID leaves and bits.
|
||||
// The kernel also exposes the presence of features to userspace through
|
||||
// a set of flags(HWCAP/HWCAP2) bits, exposed in the auxiliary vector, which
|
||||
// are necessary to read for some features (e.g. FSGSBASE).
|
||||
//
|
||||
// Common references:
|
||||
//
|
||||
// Intel:
|
||||
// - Intel SDM Volume 2, Chapter 3.2 "CPUID" (more up-to-date)
|
||||
// - Intel Application Note 485 (more detailed)
|
||||
//
|
||||
// AMD:
|
||||
// - AMD64 APM Volume 3, Appendix 3 "Obtaining Processor Information ..."
|
||||
//
|
||||
// +stateify savable
|
||||
type FeatureSet struct {
|
||||
// Function is the underlying CPUID Function.
|
||||
//
|
||||
// This is exported to allow direct calls of the underlying CPUID
|
||||
// function, where required.
|
||||
Function `state:".(Static)"`
|
||||
// hwCap stores HWCAP1/2 exposed from the elf auxiliary vector.
|
||||
hwCap hwCap
|
||||
}
|
||||
|
||||
// saveFunction saves the function as a static query.
|
||||
func (fs *FeatureSet) saveFunction() Static {
|
||||
if s, ok := fs.Function.(Static); ok {
|
||||
return s
|
||||
}
|
||||
return fs.ToStatic()
|
||||
}
|
||||
|
||||
// loadFunction saves the function as a static query.
|
||||
func (fs *FeatureSet) loadFunction(_ context.Context, s Static) {
|
||||
fs.Function = s
|
||||
}
|
||||
|
||||
// Helper to convert 3 regs into 12-byte vendor ID.
|
||||
//
|
||||
//go:nosplit
|
||||
func vendorIDFromRegs(bx, cx, dx uint32) (r [12]byte) {
|
||||
for i := uint(0); i < 4; i++ {
|
||||
b := byte(bx >> (i * 8))
|
||||
r[i] = b
|
||||
}
|
||||
|
||||
for i := uint(0); i < 4; i++ {
|
||||
b := byte(dx >> (i * 8))
|
||||
r[4+i] = b
|
||||
}
|
||||
|
||||
for i := uint(0); i < 4; i++ {
|
||||
b := byte(cx >> (i * 8))
|
||||
r[8+i] = b
|
||||
}
|
||||
|
||||
return r
|
||||
}
|
||||
|
||||
// Helper to merge a 12-byte vendor ID back to registers.
|
||||
//
|
||||
// Used by static_amd64.go.
|
||||
func regsFromVendorID(r [12]byte) (bx, cx, dx uint32) {
|
||||
bx |= uint32(r[0])
|
||||
bx |= uint32(r[1]) << 8
|
||||
bx |= uint32(r[2]) << 16
|
||||
bx |= uint32(r[3]) << 24
|
||||
cx |= uint32(r[4])
|
||||
cx |= uint32(r[5]) << 8
|
||||
cx |= uint32(r[6]) << 16
|
||||
cx |= uint32(r[7]) << 24
|
||||
dx |= uint32(r[8])
|
||||
dx |= uint32(r[9]) << 8
|
||||
dx |= uint32(r[10]) << 16
|
||||
dx |= uint32(r[10]) << 24
|
||||
return
|
||||
}
|
||||
|
||||
// VendorID is the 12-char string returned in ebx:edx:ecx for eax=0.
|
||||
//
|
||||
//go:nosplit
|
||||
func (fs FeatureSet) VendorID() [12]byte {
|
||||
_, bx, cx, dx := fs.query(vendorID)
|
||||
return vendorIDFromRegs(bx, cx, dx)
|
||||
}
|
||||
|
||||
// Helper to deconstruct signature dword.
|
||||
//
|
||||
//go:nosplit
|
||||
func signatureSplit(v uint32) (ef, em, pt, f, m, sid uint8) {
|
||||
sid = uint8(v & 0xf)
|
||||
m = uint8(v>>4) & 0xf
|
||||
f = uint8(v>>8) & 0xf
|
||||
pt = uint8(v>>12) & 0x3
|
||||
em = uint8(v>>16) & 0xf
|
||||
ef = uint8(v >> 20)
|
||||
return
|
||||
}
|
||||
|
||||
// ExtendedFamily is part of the processor signature.
|
||||
//
|
||||
//go:nosplit
|
||||
func (fs FeatureSet) ExtendedFamily() uint8 {
|
||||
ax, _, _, _ := fs.query(featureInfo)
|
||||
ef, _, _, _, _, _ := signatureSplit(ax)
|
||||
return ef
|
||||
}
|
||||
|
||||
// ExtendedModel is part of the processor signature.
|
||||
//
|
||||
//go:nosplit
|
||||
func (fs FeatureSet) ExtendedModel() uint8 {
|
||||
ax, _, _, _ := fs.query(featureInfo)
|
||||
_, em, _, _, _, _ := signatureSplit(ax)
|
||||
return em
|
||||
}
|
||||
|
||||
// ProcessorType is part of the processor signature.
|
||||
//
|
||||
//go:nosplit
|
||||
func (fs FeatureSet) ProcessorType() uint8 {
|
||||
ax, _, _, _ := fs.query(featureInfo)
|
||||
_, _, pt, _, _, _ := signatureSplit(ax)
|
||||
return pt
|
||||
}
|
||||
|
||||
// Family is part of the processor signature.
|
||||
//
|
||||
//go:nosplit
|
||||
func (fs FeatureSet) Family() uint8 {
|
||||
ax, _, _, _ := fs.query(featureInfo)
|
||||
_, _, _, f, _, _ := signatureSplit(ax)
|
||||
return f
|
||||
}
|
||||
|
||||
// Model is part of the processor signature.
|
||||
//
|
||||
//go:nosplit
|
||||
func (fs FeatureSet) Model() uint8 {
|
||||
ax, _, _, _ := fs.query(featureInfo)
|
||||
_, _, _, _, m, _ := signatureSplit(ax)
|
||||
return m
|
||||
}
|
||||
|
||||
// SteppingID is part of the processor signature.
|
||||
//
|
||||
//go:nosplit
|
||||
func (fs FeatureSet) SteppingID() uint8 {
|
||||
ax, _, _, _ := fs.query(featureInfo)
|
||||
_, _, _, _, _, sid := signatureSplit(ax)
|
||||
return sid
|
||||
}
|
||||
|
||||
// VirtualAddressBits returns the number of bits available for virtual
|
||||
// addresses.
|
||||
//
|
||||
//go:nosplit
|
||||
func (fs FeatureSet) VirtualAddressBits() uint32 {
|
||||
ax, _, _, _ := fs.query(addressSizes)
|
||||
return (ax >> 8) & 0xff
|
||||
}
|
||||
|
||||
// PhysicalAddressBits returns the number of bits available for physical
|
||||
// addresses.
|
||||
//
|
||||
//go:nosplit
|
||||
func (fs FeatureSet) PhysicalAddressBits() uint32 {
|
||||
ax, _, _, _ := fs.query(addressSizes)
|
||||
return ax & 0xff
|
||||
}
|
||||
|
||||
// CacheType describes the type of a cache, as returned in eax[4:0] for eax=4.
|
||||
type CacheType uint8
|
||||
|
||||
const (
|
||||
// cacheNull indicates that there are no more entries.
|
||||
cacheNull CacheType = iota
|
||||
|
||||
// CacheData is a data cache.
|
||||
CacheData
|
||||
|
||||
// CacheInstruction is an instruction cache.
|
||||
CacheInstruction
|
||||
|
||||
// CacheUnified is a unified instruction and data cache.
|
||||
CacheUnified
|
||||
)
|
||||
|
||||
// Cache describes the parameters of a single cache on the system.
|
||||
//
|
||||
// This is returned by the Caches method on FeatureSet.
|
||||
type Cache struct {
|
||||
// Level is the hierarchical level of this cache (L1, L2, etc).
|
||||
Level uint32
|
||||
|
||||
// Type is the type of cache.
|
||||
Type CacheType
|
||||
|
||||
// FullyAssociative indicates that entries may be placed in any block.
|
||||
FullyAssociative bool
|
||||
|
||||
// Partitions is the number of physical partitions in the cache.
|
||||
Partitions uint32
|
||||
|
||||
// Ways is the number of ways of associativity in the cache.
|
||||
Ways uint32
|
||||
|
||||
// Sets is the number of sets in the cache.
|
||||
Sets uint32
|
||||
|
||||
// InvalidateHierarchical indicates that WBINVD/INVD from threads
|
||||
// sharing this cache acts upon lower level caches for threads sharing
|
||||
// this cache.
|
||||
InvalidateHierarchical bool
|
||||
|
||||
// Inclusive indicates that this cache is inclusive of lower cache
|
||||
// levels.
|
||||
Inclusive bool
|
||||
|
||||
// DirectMapped indicates that this cache is directly mapped from
|
||||
// address, rather than using a hash function.
|
||||
DirectMapped bool
|
||||
}
|
||||
|
||||
// Caches describes the caches on the CPU.
|
||||
//
|
||||
// Only supported on Intel; requires allocation.
|
||||
func (fs FeatureSet) Caches() (caches []Cache) {
|
||||
if !fs.Intel() {
|
||||
return
|
||||
}
|
||||
// Check against the cache line, which should be consistent.
|
||||
cacheLine := fs.CacheLine()
|
||||
for i := uint32(0); ; i++ {
|
||||
out := fs.Query(In{
|
||||
Eax: uint32(intelDeterministicCacheParams),
|
||||
Ecx: i,
|
||||
})
|
||||
t := CacheType(out.Eax & 0xf)
|
||||
if t == cacheNull {
|
||||
break
|
||||
}
|
||||
lineSize := (out.Ebx & 0xfff) + 1
|
||||
if lineSize != cacheLine {
|
||||
panic(fmt.Sprintf("Mismatched cache line size: %d vs %d", lineSize, cacheLine))
|
||||
}
|
||||
caches = append(caches, Cache{
|
||||
Type: t,
|
||||
Level: (out.Eax >> 5) & 0x7,
|
||||
FullyAssociative: ((out.Eax >> 9) & 1) == 1,
|
||||
Partitions: ((out.Ebx >> 12) & 0x3ff) + 1,
|
||||
Ways: ((out.Ebx >> 22) & 0x3ff) + 1,
|
||||
Sets: out.Ecx + 1,
|
||||
InvalidateHierarchical: (out.Edx & 1) == 0,
|
||||
Inclusive: ((out.Edx >> 1) & 1) == 1,
|
||||
DirectMapped: ((out.Edx >> 2) & 1) == 0,
|
||||
})
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// CacheLine is the size of a cache line in bytes.
|
||||
//
|
||||
// All caches use the same line size. This is not enforced in the CPUID
|
||||
// encoding, but is true on all known x86 processors.
|
||||
//
|
||||
//go:nosplit
|
||||
func (fs FeatureSet) CacheLine() uint32 {
|
||||
_, bx, _, _ := fs.query(featureInfo)
|
||||
return 8 * (bx >> 8) & 0xff
|
||||
}
|
||||
|
||||
// HasFeature tests whether or not a feature is in the given feature set.
|
||||
//
|
||||
// This function is safe to call from a nosplit context, as long as the
|
||||
// FeatureSet does not have any masked features.
|
||||
//
|
||||
//go:nosplit
|
||||
func (fs FeatureSet) HasFeature(feature Feature) bool {
|
||||
return feature.check(fs)
|
||||
}
|
||||
|
||||
// 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. The bogomips field is simply made up.
|
||||
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)
|
||||
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, "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.
|
||||
fmt.Fprintf(w, "cpu MHz\t\t: %.3f\n", cpuFreqMHz)
|
||||
fmt.Fprintf(w, "physical id\t: 0\n") // Pretend all CPUs are in the same socket.
|
||||
fmt.Fprintf(w, "siblings\t: %d\n", numCPU)
|
||||
fmt.Fprintf(w, "core id\t\t: %d\n", cpu)
|
||||
fmt.Fprintf(w, "cpu cores\t: %d\n", numCPU) // Pretend each CPU is a distinct core (rather than a hyperthread).
|
||||
fmt.Fprintf(w, "apicid\t\t: %d\n", cpu)
|
||||
fmt.Fprintf(w, "initial apicid\t: %d\n", cpu)
|
||||
fmt.Fprintf(w, "fpu\t\t: yes\n")
|
||||
fmt.Fprintf(w, "fpu_exception\t: yes\n")
|
||||
fmt.Fprintf(w, "cpuid level\t: %d\n", uint32(xSaveInfo)) // Same as ax in vendorID.
|
||||
fmt.Fprintf(w, "wp\t\t: yes\n")
|
||||
fmt.Fprintf(w, "flags\t\t: %s\n", fs.FlagString())
|
||||
fmt.Fprintf(w, "bogomips\t: %.02f\n", cpuFreqMHz) // It's bogus anyway.
|
||||
fmt.Fprintf(w, "clflush size\t: %d\n", fs.CacheLine())
|
||||
fmt.Fprintf(w, "cache_alignment\t: %d\n", fs.CacheLine())
|
||||
fmt.Fprintf(w, "address sizes\t: %d bits physical, %d bits virtual\n", 46, 48)
|
||||
fmt.Fprintf(w, "power management:\n") // This is always here, but can be blank.
|
||||
fmt.Fprintf(w, "\n") // The /proc/cpuinfo file ends with an extra newline.
|
||||
}
|
||||
|
||||
var (
|
||||
authenticAMD = [12]byte{'A', 'u', 't', 'h', 'e', 'n', 't', 'i', 'c', 'A', 'M', 'D'}
|
||||
genuineIntel = [12]byte{'G', 'e', 'n', 'u', 'i', 'n', 'e', 'I', 'n', 't', 'e', 'l'}
|
||||
)
|
||||
|
||||
// AMD returns true if fs describes an AMD CPU.
|
||||
//
|
||||
//go:nosplit
|
||||
func (fs FeatureSet) AMD() bool {
|
||||
return fs.VendorID() == authenticAMD
|
||||
}
|
||||
|
||||
// Intel returns true if fs describes an Intel CPU.
|
||||
//
|
||||
//go:nosplit
|
||||
func (fs FeatureSet) Intel() bool {
|
||||
return fs.VendorID() == genuineIntel
|
||||
}
|
||||
|
||||
// Leaf 0 of xsaveinfo function returns the size for currently
|
||||
// enabled xsave features in ebx, the maximum size if all valid
|
||||
// features are saved with xsave in ecx, and valid XCR0 bits in
|
||||
// edx:eax.
|
||||
//
|
||||
// If xSaveInfo isn't supported, cpuid will not fault but will
|
||||
// return bogus values.
|
||||
var (
|
||||
xsaveSize = native(In{Eax: uint32(xSaveInfo)}).Ebx
|
||||
maxXsaveSize = native(In{Eax: uint32(xSaveInfo)}).Ecx
|
||||
amxTileCfgSize = native(In{Eax: uint32(xSaveInfo), Ecx: 17}).Eax
|
||||
amxTileDataSize = native(In{Eax: uint32(xSaveInfo), Ecx: 18}).Eax
|
||||
)
|
||||
|
||||
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.
|
||||
//
|
||||
// See Intel® 64 and IA-32 Architectures Software Developer’s Manual Vol.1
|
||||
// section 13.3 for details.
|
||||
XCR0AMXMask = uint64((1 << 17) | (1 << 18))
|
||||
)
|
||||
|
||||
// ExtendedStateSize returns the number of bytes needed to save the "extended
|
||||
// state" for the enabled features and the boundary it must be aligned to.
|
||||
// Extended state includes floating point registers, and other cpu state that's
|
||||
// not associated with the normal task context.
|
||||
//
|
||||
// Note: the return value matches the size of signal FP state frames.
|
||||
// Look at check_xstate_in_sigframe() in the kernel sources for more details.
|
||||
//
|
||||
//go:nosplit
|
||||
func (fs FeatureSet) ExtendedStateSize() (size, align uint) {
|
||||
if fs.UseXsave() {
|
||||
return uint(xsaveSize), 64
|
||||
}
|
||||
|
||||
// If we don't support xsave, we fall back to fxsave, which requires
|
||||
// 512 bytes aligned to 16 bytes.
|
||||
return 512, 16
|
||||
}
|
||||
|
||||
// AMXExtendedStateSize returns the number of bytes within the "extended state"
|
||||
// area that is used for AMX.
|
||||
func (fs FeatureSet) AMXExtendedStateSize() uint {
|
||||
if fs.UseXsave() {
|
||||
xcr0 := xgetbv(0)
|
||||
if (xcr0 & XCR0AMXMask) != 0 {
|
||||
return uint(amxTileCfgSize + amxTileDataSize)
|
||||
}
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
// ValidXCR0Mask returns the valid bits in control register XCR0.
|
||||
//
|
||||
// Always exclude AMX bits, because we do not support it.
|
||||
// TODO(gvisor.dev/issues/9896): Implement AMX Support.
|
||||
//
|
||||
//go:nosplit
|
||||
func (fs FeatureSet) ValidXCR0Mask() uint64 {
|
||||
if !fs.HasFeature(X86FeatureXSAVE) {
|
||||
return 0
|
||||
}
|
||||
ax, _, _, dx := fs.query(xSaveInfo)
|
||||
return (uint64(dx)<<32 | uint64(ax)) &^ XCR0AMXMask
|
||||
}
|
||||
|
||||
// UseXsave returns the choice of fp state saving instruction.
|
||||
//
|
||||
//go:nosplit
|
||||
func (fs FeatureSet) UseXsave() bool {
|
||||
return fs.HasFeature(X86FeatureXSAVE) && fs.HasFeature(X86FeatureOSXSAVE)
|
||||
}
|
||||
|
||||
// UseXsaveopt returns true if 'fs' supports the "xsaveopt" instruction.
|
||||
//
|
||||
//go:nosplit
|
||||
func (fs FeatureSet) UseXsaveopt() bool {
|
||||
return fs.UseXsave() && fs.HasFeature(X86FeatureXSAVEOPT)
|
||||
}
|
||||
|
||||
// UseXsavec returns true if 'fs' supports the "xsavec" instruction.
|
||||
//
|
||||
//go:nosplit
|
||||
func (fs FeatureSet) UseXsavec() bool {
|
||||
return fs.UseXsaveopt() && fs.HasFeature(X86FeatureXSAVEC)
|
||||
}
|
||||
|
||||
// UseFSGSBASE returns true if 'fs' supports the (RD|WR)(FS|GS)BASE instructions.
|
||||
func (fs FeatureSet) UseFSGSBASE() bool {
|
||||
HWCAP2_FSGSBASE := uint64(1) << 1
|
||||
return fs.HasFeature(X86FeatureFSGSBase) && ((fs.hwCap.hwCap2 & HWCAP2_FSGSBASE) != 0)
|
||||
}
|
||||
|
||||
// archCheckHostCompatible checks for compatibility.
|
||||
func (fs FeatureSet) archCheckHostCompatible(hfs FeatureSet) error {
|
||||
// The size of a cache line must match, as it is critical to correctly
|
||||
// utilizing CLFLUSH. Other cache properties are allowed to change, as
|
||||
// they are not important to correctness.
|
||||
fsCache := fs.CacheLine()
|
||||
hostCache := hfs.CacheLine()
|
||||
if fsCache != hostCache {
|
||||
return &ErrIncompatible{
|
||||
reason: fmt.Sprintf("CPU cache line size %d incompatible with host cache line size %d", fsCache, hostCache),
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
110
vendor/gvisor.dev/gvisor/pkg/cpuid/cpuid_amd64_state_autogen.go
vendored
Normal file
110
vendor/gvisor.dev/gvisor/pkg/cpuid/cpuid_amd64_state_autogen.go
vendored
Normal file
@@ -0,0 +1,110 @@
|
||||
// automatically generated by stateify.
|
||||
|
||||
//go:build amd64 && amd64 && amd64 && amd64
|
||||
// +build amd64,amd64,amd64,amd64
|
||||
|
||||
package cpuid
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"gvisor.dev/gvisor/pkg/state"
|
||||
)
|
||||
|
||||
func (fs *FeatureSet) StateTypeName() string {
|
||||
return "pkg/cpuid.FeatureSet"
|
||||
}
|
||||
|
||||
func (fs *FeatureSet) StateFields() []string {
|
||||
return []string{
|
||||
"Function",
|
||||
"hwCap",
|
||||
}
|
||||
}
|
||||
|
||||
func (fs *FeatureSet) beforeSave() {}
|
||||
|
||||
// +checklocksignore
|
||||
func (fs *FeatureSet) StateSave(stateSinkObject state.Sink) {
|
||||
fs.beforeSave()
|
||||
var FunctionValue Static
|
||||
FunctionValue = fs.saveFunction()
|
||||
stateSinkObject.SaveValue(0, FunctionValue)
|
||||
stateSinkObject.Save(1, &fs.hwCap)
|
||||
}
|
||||
|
||||
func (fs *FeatureSet) afterLoad(context.Context) {}
|
||||
|
||||
// +checklocksignore
|
||||
func (fs *FeatureSet) StateLoad(ctx context.Context, stateSourceObject state.Source) {
|
||||
stateSourceObject.Load(1, &fs.hwCap)
|
||||
stateSourceObject.LoadValue(0, new(Static), func(y any) { fs.loadFunction(ctx, y.(Static)) })
|
||||
}
|
||||
|
||||
func (i *In) StateTypeName() string {
|
||||
return "pkg/cpuid.In"
|
||||
}
|
||||
|
||||
func (i *In) StateFields() []string {
|
||||
return []string{
|
||||
"Eax",
|
||||
"Ecx",
|
||||
}
|
||||
}
|
||||
|
||||
func (i *In) beforeSave() {}
|
||||
|
||||
// +checklocksignore
|
||||
func (i *In) StateSave(stateSinkObject state.Sink) {
|
||||
i.beforeSave()
|
||||
stateSinkObject.Save(0, &i.Eax)
|
||||
stateSinkObject.Save(1, &i.Ecx)
|
||||
}
|
||||
|
||||
func (i *In) afterLoad(context.Context) {}
|
||||
|
||||
// +checklocksignore
|
||||
func (i *In) StateLoad(ctx context.Context, stateSourceObject state.Source) {
|
||||
stateSourceObject.Load(0, &i.Eax)
|
||||
stateSourceObject.Load(1, &i.Ecx)
|
||||
}
|
||||
|
||||
func (o *Out) StateTypeName() string {
|
||||
return "pkg/cpuid.Out"
|
||||
}
|
||||
|
||||
func (o *Out) StateFields() []string {
|
||||
return []string{
|
||||
"Eax",
|
||||
"Ebx",
|
||||
"Ecx",
|
||||
"Edx",
|
||||
}
|
||||
}
|
||||
|
||||
func (o *Out) beforeSave() {}
|
||||
|
||||
// +checklocksignore
|
||||
func (o *Out) StateSave(stateSinkObject state.Sink) {
|
||||
o.beforeSave()
|
||||
stateSinkObject.Save(0, &o.Eax)
|
||||
stateSinkObject.Save(1, &o.Ebx)
|
||||
stateSinkObject.Save(2, &o.Ecx)
|
||||
stateSinkObject.Save(3, &o.Edx)
|
||||
}
|
||||
|
||||
func (o *Out) afterLoad(context.Context) {}
|
||||
|
||||
// +checklocksignore
|
||||
func (o *Out) StateLoad(ctx context.Context, stateSourceObject state.Source) {
|
||||
stateSourceObject.Load(0, &o.Eax)
|
||||
stateSourceObject.Load(1, &o.Ebx)
|
||||
stateSourceObject.Load(2, &o.Ecx)
|
||||
stateSourceObject.Load(3, &o.Edx)
|
||||
}
|
||||
|
||||
func init() {
|
||||
state.Register((*FeatureSet)(nil))
|
||||
state.Register((*In)(nil))
|
||||
state.Register((*Out)(nil))
|
||||
}
|
||||
110
vendor/gvisor.dev/gvisor/pkg/cpuid/cpuid_arm64.go
vendored
Normal file
110
vendor/gvisor.dev/gvisor/pkg/cpuid/cpuid_arm64.go
vendored
Normal file
@@ -0,0 +1,110 @@
|
||||
// Copyright 2020 The gVisor Authors.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
//go:build arm64
|
||||
// +build arm64
|
||||
|
||||
package cpuid
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
)
|
||||
|
||||
// FeatureSet for ARM64 is defined as a static set of bits.
|
||||
//
|
||||
// ARM64 doesn't have a CPUID equivalent, which means it has no architected
|
||||
// discovery mechanism for hardware features available to userspace code at
|
||||
// EL0. The kernel exposes the presence of these features to userspace through
|
||||
// a set of flags(HWCAP/HWCAP2) bits, exposed in the auxiliary vector. See
|
||||
// Documentation/arm64/elf_hwcaps.rst for more info.
|
||||
//
|
||||
// Currently, only the HWCAP bits are supported.
|
||||
//
|
||||
// +stateify savable
|
||||
type FeatureSet struct {
|
||||
hwCap hwCap
|
||||
cpuFreqMHz float64
|
||||
cpuImplHex uint64
|
||||
cpuArchDec uint64
|
||||
cpuVarHex uint64
|
||||
cpuPartHex uint64
|
||||
cpuRevDec uint64
|
||||
}
|
||||
|
||||
// CPUImplementer is part of the processor signature.
|
||||
func (fs FeatureSet) CPUImplementer() uint8 {
|
||||
return uint8(fs.cpuImplHex)
|
||||
}
|
||||
|
||||
// CPUArchitecture is part of the processor signature.
|
||||
func (fs FeatureSet) CPUArchitecture() uint8 {
|
||||
return uint8(fs.cpuArchDec)
|
||||
}
|
||||
|
||||
// CPUVariant is part of the processor signature.
|
||||
func (fs FeatureSet) CPUVariant() uint8 {
|
||||
return uint8(fs.cpuVarHex)
|
||||
}
|
||||
|
||||
// CPUPartnum is part of the processor signature.
|
||||
func (fs FeatureSet) CPUPartnum() uint16 {
|
||||
return uint16(fs.cpuPartHex)
|
||||
}
|
||||
|
||||
// CPURevision is part of the processor signature.
|
||||
func (fs FeatureSet) CPURevision() uint8 {
|
||||
return uint8(fs.cpuRevDec)
|
||||
}
|
||||
|
||||
// ExtendedStateSize returns the number of bytes needed to save the "extended
|
||||
// state" for this processor and the boundary it must be aligned to. Extended
|
||||
// state includes floating point(NEON) registers, and other cpu state that's not
|
||||
// associated with the normal task context.
|
||||
func (fs FeatureSet) ExtendedStateSize() (size, align uint) {
|
||||
// ARMv8 provide 32x128bits NEON registers.
|
||||
//
|
||||
// Ref arch/arm64/include/uapi/asm/ptrace.h
|
||||
// struct user_fpsimd_state {
|
||||
// __uint128_t vregs[32];
|
||||
// __u32 fpsr;
|
||||
// __u32 fpcr;
|
||||
// __u32 __reserved[2];
|
||||
// };
|
||||
return 528, 16
|
||||
}
|
||||
|
||||
// HasFeature checks for the presence of a feature.
|
||||
func (fs FeatureSet) HasFeature(feature Feature) bool {
|
||||
return fs.hwCap.hwCap1&(1<<feature) != 0
|
||||
}
|
||||
|
||||
// WriteCPUInfoTo is to generate a section of one cpu in /proc/cpuinfo. This is
|
||||
// a minimal /proc/cpuinfo, and the bogomips field is simply made up.
|
||||
func (fs FeatureSet) WriteCPUInfoTo(cpu, numCPU uint, w io.Writer) {
|
||||
fmt.Fprintf(w, "processor\t: %d\n", cpu)
|
||||
fmt.Fprintf(w, "BogoMIPS\t: %.02f\n", fs.cpuFreqMHz) // It's bogus anyway.
|
||||
fmt.Fprintf(w, "Features\t\t: %s\n", fs.FlagString())
|
||||
fmt.Fprintf(w, "CPU implementer\t: 0x%x\n", fs.cpuImplHex)
|
||||
fmt.Fprintf(w, "CPU architecture\t: %d\n", fs.cpuArchDec)
|
||||
fmt.Fprintf(w, "CPU variant\t: 0x%x\n", fs.cpuVarHex)
|
||||
fmt.Fprintf(w, "CPU part\t: 0x%x\n", fs.cpuPartHex)
|
||||
fmt.Fprintf(w, "CPU revision\t: %d\n", fs.cpuRevDec)
|
||||
fmt.Fprintf(w, "\n") // The /proc/cpuinfo file ends with an extra newline.
|
||||
}
|
||||
|
||||
// archCheckHostCompatible is a noop on arm64.
|
||||
func (FeatureSet) archCheckHostCompatible(FeatureSet) error {
|
||||
return nil
|
||||
}
|
||||
59
vendor/gvisor.dev/gvisor/pkg/cpuid/cpuid_arm64_state_autogen.go
vendored
Normal file
59
vendor/gvisor.dev/gvisor/pkg/cpuid/cpuid_arm64_state_autogen.go
vendored
Normal file
@@ -0,0 +1,59 @@
|
||||
// automatically generated by stateify.
|
||||
|
||||
//go:build arm64 && arm64 && arm64
|
||||
// +build arm64,arm64,arm64
|
||||
|
||||
package cpuid
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"gvisor.dev/gvisor/pkg/state"
|
||||
)
|
||||
|
||||
func (fs *FeatureSet) StateTypeName() string {
|
||||
return "pkg/cpuid.FeatureSet"
|
||||
}
|
||||
|
||||
func (fs *FeatureSet) StateFields() []string {
|
||||
return []string{
|
||||
"hwCap",
|
||||
"cpuFreqMHz",
|
||||
"cpuImplHex",
|
||||
"cpuArchDec",
|
||||
"cpuVarHex",
|
||||
"cpuPartHex",
|
||||
"cpuRevDec",
|
||||
}
|
||||
}
|
||||
|
||||
func (fs *FeatureSet) beforeSave() {}
|
||||
|
||||
// +checklocksignore
|
||||
func (fs *FeatureSet) StateSave(stateSinkObject state.Sink) {
|
||||
fs.beforeSave()
|
||||
stateSinkObject.Save(0, &fs.hwCap)
|
||||
stateSinkObject.Save(1, &fs.cpuFreqMHz)
|
||||
stateSinkObject.Save(2, &fs.cpuImplHex)
|
||||
stateSinkObject.Save(3, &fs.cpuArchDec)
|
||||
stateSinkObject.Save(4, &fs.cpuVarHex)
|
||||
stateSinkObject.Save(5, &fs.cpuPartHex)
|
||||
stateSinkObject.Save(6, &fs.cpuRevDec)
|
||||
}
|
||||
|
||||
func (fs *FeatureSet) afterLoad(context.Context) {}
|
||||
|
||||
// +checklocksignore
|
||||
func (fs *FeatureSet) StateLoad(ctx context.Context, stateSourceObject state.Source) {
|
||||
stateSourceObject.Load(0, &fs.hwCap)
|
||||
stateSourceObject.Load(1, &fs.cpuFreqMHz)
|
||||
stateSourceObject.Load(2, &fs.cpuImplHex)
|
||||
stateSourceObject.Load(3, &fs.cpuArchDec)
|
||||
stateSourceObject.Load(4, &fs.cpuVarHex)
|
||||
stateSourceObject.Load(5, &fs.cpuPartHex)
|
||||
stateSourceObject.Load(6, &fs.cpuRevDec)
|
||||
}
|
||||
|
||||
func init() {
|
||||
state.Register((*FeatureSet)(nil))
|
||||
}
|
||||
41
vendor/gvisor.dev/gvisor/pkg/cpuid/cpuid_state_autogen.go
vendored
Normal file
41
vendor/gvisor.dev/gvisor/pkg/cpuid/cpuid_state_autogen.go
vendored
Normal file
@@ -0,0 +1,41 @@
|
||||
// automatically generated by stateify.
|
||||
|
||||
package cpuid
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"gvisor.dev/gvisor/pkg/state"
|
||||
)
|
||||
|
||||
func (h *hwCap) StateTypeName() string {
|
||||
return "pkg/cpuid.hwCap"
|
||||
}
|
||||
|
||||
func (h *hwCap) StateFields() []string {
|
||||
return []string{
|
||||
"hwCap1",
|
||||
"hwCap2",
|
||||
}
|
||||
}
|
||||
|
||||
func (h *hwCap) beforeSave() {}
|
||||
|
||||
// +checklocksignore
|
||||
func (h *hwCap) StateSave(stateSinkObject state.Sink) {
|
||||
h.beforeSave()
|
||||
stateSinkObject.Save(0, &h.hwCap1)
|
||||
stateSinkObject.Save(1, &h.hwCap2)
|
||||
}
|
||||
|
||||
func (h *hwCap) afterLoad(context.Context) {}
|
||||
|
||||
// +checklocksignore
|
||||
func (h *hwCap) StateLoad(ctx context.Context, stateSourceObject state.Source) {
|
||||
stateSourceObject.Load(0, &h.hwCap1)
|
||||
stateSourceObject.Load(1, &h.hwCap2)
|
||||
}
|
||||
|
||||
func init() {
|
||||
state.Register((*hwCap)(nil))
|
||||
}
|
||||
664
vendor/gvisor.dev/gvisor/pkg/cpuid/features_amd64.go
vendored
Normal file
664
vendor/gvisor.dev/gvisor/pkg/cpuid/features_amd64.go
vendored
Normal file
@@ -0,0 +1,664 @@
|
||||
// Copyright 2019 The gVisor Authors.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
//go:build amd64
|
||||
// +build amd64
|
||||
|
||||
package cpuid
|
||||
|
||||
// block is a collection of 32 Feature bits.
|
||||
type block int
|
||||
|
||||
// blockSize is the number of bits in a single block.
|
||||
const blockSize = 32
|
||||
|
||||
// featureID returns the feature identified by the given block and bit.
|
||||
//
|
||||
// Feature bits are numbered according to "blocks". Each block is 32 bits, and
|
||||
// feature bits from the same source (cpuid leaf/level) are in the same block.
|
||||
func featureID(b block, bit int) Feature {
|
||||
return Feature(blockSize*int(b) + bit)
|
||||
}
|
||||
|
||||
// block returns the block associated with the feature.
|
||||
func (f Feature) block() block {
|
||||
return block(f / blockSize)
|
||||
}
|
||||
|
||||
// Bit returns the bit associated with the feature.
|
||||
func (f Feature) bit() uint32 {
|
||||
return uint32(1 << (f % blockSize))
|
||||
}
|
||||
|
||||
// ChangeableSet is a feature set that can allows changes.
|
||||
type ChangeableSet interface {
|
||||
Query(in In) Out
|
||||
Set(in In, out Out)
|
||||
}
|
||||
|
||||
// Set sets the given feature.
|
||||
func (f Feature) Set(s ChangeableSet) {
|
||||
f.set(s, true)
|
||||
}
|
||||
|
||||
// Unset unsets the given feature.
|
||||
func (f Feature) Unset(s ChangeableSet) {
|
||||
f.set(s, false)
|
||||
}
|
||||
|
||||
// set sets the given feature.
|
||||
func (f Feature) set(s ChangeableSet, on bool) {
|
||||
switch f.block() {
|
||||
case 0:
|
||||
out := s.Query(In{Eax: uint32(featureInfo)})
|
||||
if on {
|
||||
out.Ecx |= f.bit()
|
||||
} else {
|
||||
out.Ecx &^= f.bit()
|
||||
}
|
||||
s.Set(In{Eax: uint32(featureInfo)}, out)
|
||||
case 1:
|
||||
out := s.Query(In{Eax: uint32(featureInfo)})
|
||||
if on {
|
||||
out.Edx |= f.bit()
|
||||
} else {
|
||||
out.Edx &^= f.bit()
|
||||
}
|
||||
s.Set(In{Eax: uint32(featureInfo)}, out)
|
||||
case 2:
|
||||
out := s.Query(In{Eax: uint32(extendedFeatureInfo)})
|
||||
if on {
|
||||
out.Ebx |= f.bit()
|
||||
} else {
|
||||
out.Ebx &^= f.bit()
|
||||
}
|
||||
s.Set(In{Eax: uint32(extendedFeatureInfo)}, out)
|
||||
case 3:
|
||||
out := s.Query(In{Eax: uint32(extendedFeatureInfo)})
|
||||
if on {
|
||||
out.Ecx |= f.bit()
|
||||
} else {
|
||||
out.Ecx &^= f.bit()
|
||||
}
|
||||
s.Set(In{Eax: uint32(extendedFeatureInfo)}, out)
|
||||
case 4:
|
||||
// Need to turn on the bit in block 0.
|
||||
out := s.Query(In{Eax: uint32(featureInfo)})
|
||||
out.Ecx |= (1 << 26)
|
||||
s.Set(In{Eax: uint32(featureInfo)}, out)
|
||||
|
||||
out = s.Query(In{Eax: xSaveInfoSub.eax(), Ecx: xSaveInfoSub.ecx()})
|
||||
if on {
|
||||
out.Eax |= f.bit()
|
||||
} else {
|
||||
out.Eax &^= f.bit()
|
||||
}
|
||||
s.Set(In{Eax: xSaveInfoSub.eax(), Ecx: xSaveInfoSub.ecx()}, out)
|
||||
case 5, 6:
|
||||
// Need to enable extended features.
|
||||
out := s.Query(In{Eax: uint32(extendedFunctionInfo)})
|
||||
if out.Eax < uint32(extendedFeatures) {
|
||||
out.Eax = uint32(extendedFeatures)
|
||||
}
|
||||
s.Set(In{Eax: uint32(extendedFunctionInfo)}, out)
|
||||
out = s.Query(In{Eax: uint32(extendedFeatures)})
|
||||
if f.block() == 5 {
|
||||
if on {
|
||||
out.Ecx |= f.bit()
|
||||
} else {
|
||||
out.Ecx &^= f.bit()
|
||||
}
|
||||
} else {
|
||||
if on {
|
||||
out.Edx |= f.bit()
|
||||
} else {
|
||||
out.Edx &^= f.bit()
|
||||
}
|
||||
}
|
||||
s.Set(In{Eax: uint32(extendedFeatures)}, out)
|
||||
case 7:
|
||||
out := s.Query(In{Eax: uint32(extendedFeatureInfo)})
|
||||
if on {
|
||||
out.Edx |= f.bit()
|
||||
} else {
|
||||
out.Edx &^= f.bit()
|
||||
}
|
||||
s.Set(In{Eax: uint32(extendedFeatureInfo)}, out)
|
||||
}
|
||||
}
|
||||
|
||||
// check checks for the given feature.
|
||||
//
|
||||
//go:nosplit
|
||||
func (f Feature) check(fs FeatureSet) bool {
|
||||
switch f.block() {
|
||||
case 0:
|
||||
_, _, cx, _ := fs.query(featureInfo)
|
||||
return (cx & f.bit()) != 0
|
||||
case 1:
|
||||
_, _, _, dx := fs.query(featureInfo)
|
||||
return (dx & f.bit()) != 0
|
||||
case 2:
|
||||
_, bx, _, _ := fs.query(extendedFeatureInfo)
|
||||
return (bx & f.bit()) != 0
|
||||
case 3:
|
||||
_, _, cx, _ := fs.query(extendedFeatureInfo)
|
||||
return (cx & f.bit()) != 0
|
||||
case 4:
|
||||
// Need to check appropriate bit in block 0.
|
||||
_, _, cx, _ := fs.query(featureInfo)
|
||||
if (cx & (1 << 26)) == 0 {
|
||||
return false
|
||||
}
|
||||
ax, _, _, _ := fs.query(xSaveInfoSub)
|
||||
return (ax & f.bit()) != 0
|
||||
case 5, 6:
|
||||
// eax=0x80000000 gets supported extended levels. We use this
|
||||
// to determine if there are any non-zero block 4 or block 6
|
||||
// bits to find.
|
||||
ax, _, _, _ := fs.query(extendedFunctionInfo)
|
||||
if ax >= uint32(extendedFeatures) {
|
||||
_, _, cx, dx := fs.query(extendedFeatures)
|
||||
if f.block() == 5 {
|
||||
return (cx & f.bit()) != 0
|
||||
}
|
||||
// Ignore features duplicated from block 1 on AMD.
|
||||
// These bits are reserved on Intel.
|
||||
return ((dx &^ block6DuplicateMask) & f.bit()) != 0
|
||||
}
|
||||
return false
|
||||
case 7:
|
||||
_, _, _, dx := fs.query(extendedFeatureInfo)
|
||||
return (dx & f.bit()) != 0
|
||||
default:
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
// Block 0 constants are all of the "basic" feature bits returned by a cpuid in
|
||||
// ecx with eax=1.
|
||||
const (
|
||||
X86FeatureSSE3 Feature = iota
|
||||
X86FeaturePCLMULDQ
|
||||
X86FeatureDTES64
|
||||
X86FeatureMONITOR
|
||||
X86FeatureDSCPL
|
||||
X86FeatureVMX
|
||||
X86FeatureSMX
|
||||
X86FeatureEST
|
||||
X86FeatureTM2
|
||||
X86FeatureSSSE3 // Not a typo, "supplemental" SSE3.
|
||||
X86FeatureCNXTID
|
||||
X86FeatureSDBG
|
||||
X86FeatureFMA
|
||||
X86FeatureCX16
|
||||
X86FeatureXTPR
|
||||
X86FeaturePDCM
|
||||
_ // ecx bit 16 is reserved.
|
||||
X86FeaturePCID
|
||||
X86FeatureDCA
|
||||
X86FeatureSSE4_1
|
||||
X86FeatureSSE4_2
|
||||
X86FeatureX2APIC
|
||||
X86FeatureMOVBE
|
||||
X86FeaturePOPCNT
|
||||
X86FeatureTSCD
|
||||
X86FeatureAES
|
||||
X86FeatureXSAVE
|
||||
X86FeatureOSXSAVE
|
||||
X86FeatureAVX
|
||||
X86FeatureF16C
|
||||
X86FeatureRDRAND
|
||||
X86FeatureHypervisor
|
||||
)
|
||||
|
||||
// Block 1 constants are all of the "basic" feature bits returned by a cpuid in
|
||||
// edx with eax=1.
|
||||
const (
|
||||
X86FeatureFPU Feature = 32 + iota
|
||||
X86FeatureVME
|
||||
X86FeatureDE
|
||||
X86FeaturePSE
|
||||
X86FeatureTSC
|
||||
X86FeatureMSR
|
||||
X86FeaturePAE
|
||||
X86FeatureMCE
|
||||
X86FeatureCX8
|
||||
X86FeatureAPIC
|
||||
_ // edx bit 10 is reserved.
|
||||
X86FeatureSEP
|
||||
X86FeatureMTRR
|
||||
X86FeaturePGE
|
||||
X86FeatureMCA
|
||||
X86FeatureCMOV
|
||||
X86FeaturePAT
|
||||
X86FeaturePSE36
|
||||
X86FeaturePSN
|
||||
X86FeatureCLFSH
|
||||
_ // edx bit 20 is reserved.
|
||||
X86FeatureDS
|
||||
X86FeatureACPI
|
||||
X86FeatureMMX
|
||||
X86FeatureFXSR
|
||||
X86FeatureSSE
|
||||
X86FeatureSSE2
|
||||
X86FeatureSS
|
||||
X86FeatureHTT
|
||||
X86FeatureTM
|
||||
X86FeatureIA64
|
||||
X86FeaturePBE
|
||||
)
|
||||
|
||||
// Block 2 bits are the "structured extended" features returned in ebx for
|
||||
// eax=7, ecx=0.
|
||||
const (
|
||||
X86FeatureFSGSBase Feature = 2*32 + iota
|
||||
X86FeatureTSC_ADJUST
|
||||
_ // ebx bit 2 is reserved.
|
||||
X86FeatureBMI1
|
||||
X86FeatureHLE
|
||||
X86FeatureAVX2
|
||||
X86FeatureFDP_EXCPTN_ONLY
|
||||
X86FeatureSMEP
|
||||
X86FeatureBMI2
|
||||
X86FeatureERMS
|
||||
X86FeatureINVPCID
|
||||
X86FeatureRTM
|
||||
X86FeatureCQM
|
||||
X86FeatureFPCSDS
|
||||
X86FeatureMPX
|
||||
X86FeatureRDT
|
||||
X86FeatureAVX512F
|
||||
X86FeatureAVX512DQ
|
||||
X86FeatureRDSEED
|
||||
X86FeatureADX
|
||||
X86FeatureSMAP
|
||||
X86FeatureAVX512IFMA
|
||||
X86FeaturePCOMMIT
|
||||
X86FeatureCLFLUSHOPT
|
||||
X86FeatureCLWB
|
||||
X86FeatureIPT // Intel processor trace.
|
||||
X86FeatureAVX512PF
|
||||
X86FeatureAVX512ER
|
||||
X86FeatureAVX512CD
|
||||
X86FeatureSHA
|
||||
X86FeatureAVX512BW
|
||||
X86FeatureAVX512VL
|
||||
)
|
||||
|
||||
// Block 3 bits are the "extended" features returned in ecx for eax=7, ecx=0.
|
||||
const (
|
||||
X86FeaturePREFETCHWT1 Feature = 3*32 + iota
|
||||
X86FeatureAVX512VBMI
|
||||
X86FeatureUMIP
|
||||
X86FeaturePKU
|
||||
X86FeatureOSPKE
|
||||
X86FeatureWAITPKG
|
||||
X86FeatureAVX512_VBMI2
|
||||
X86FeatureCET_SS
|
||||
X86FeatureGFNI
|
||||
X86FeatureVAES
|
||||
X86FeatureVPCLMULQDQ
|
||||
X86FeatureAVX512_VNNI
|
||||
X86FeatureAVX512_BITALG
|
||||
X86FeatureTME
|
||||
X86FeatureAVX512_VPOPCNTDQ
|
||||
_ // ecx bit 15 is reserved
|
||||
X86FeatureLA57
|
||||
// ecx bits 17-21 are reserved
|
||||
_
|
||||
_
|
||||
_
|
||||
_
|
||||
_
|
||||
X86FeatureRDPID
|
||||
// ecx bits 23-24 are reserved
|
||||
_
|
||||
_
|
||||
X86FeatureCLDEMOTE
|
||||
_ // ecx bit 26 is reserved
|
||||
X86FeatureMOVDIRI
|
||||
X86FeatureMOVDIR64B
|
||||
)
|
||||
|
||||
// Block 4 constants are for xsave capabilities in CPUID.(EAX=0DH,ECX=01H):EAX.
|
||||
// The CPUID leaf is available only if 'X86FeatureXSAVE' is present.
|
||||
const (
|
||||
X86FeatureXSAVEOPT Feature = 4*32 + iota
|
||||
X86FeatureXSAVEC
|
||||
X86FeatureXGETBV1
|
||||
X86FeatureXSAVES
|
||||
// EAX[31:4] are reserved.
|
||||
)
|
||||
|
||||
// Block 5 constants are the extended feature bits in
|
||||
// CPUID.(EAX=0x80000001):ECX.
|
||||
const (
|
||||
X86FeatureLAHF64 Feature = 5*32 + iota
|
||||
X86FeatureCMP_LEGACY
|
||||
X86FeatureSVM
|
||||
X86FeatureEXTAPIC
|
||||
X86FeatureCR8_LEGACY
|
||||
X86FeatureLZCNT
|
||||
X86FeatureSSE4A
|
||||
X86FeatureMISALIGNSSE
|
||||
X86FeaturePREFETCHW
|
||||
X86FeatureOSVW
|
||||
X86FeatureIBS
|
||||
X86FeatureXOP
|
||||
X86FeatureSKINIT
|
||||
X86FeatureWDT
|
||||
_ // ecx bit 14 is reserved.
|
||||
X86FeatureLWP
|
||||
X86FeatureFMA4
|
||||
X86FeatureTCE
|
||||
_ // ecx bit 18 is reserved.
|
||||
_ // ecx bit 19 is reserved.
|
||||
_ // ecx bit 20 is reserved.
|
||||
X86FeatureTBM
|
||||
X86FeatureTOPOLOGY
|
||||
X86FeaturePERFCTR_CORE
|
||||
X86FeaturePERFCTR_NB
|
||||
_ // ecx bit 25 is reserved.
|
||||
X86FeatureBPEXT
|
||||
X86FeaturePERFCTR_TSC
|
||||
X86FeaturePERFCTR_LLC
|
||||
X86FeatureMWAITX
|
||||
X86FeatureADMSKEXTN
|
||||
_ // ecx bit 31 is reserved.
|
||||
)
|
||||
|
||||
// Block 6 constants are the extended feature bits in
|
||||
// CPUID.(EAX=0x80000001):EDX.
|
||||
//
|
||||
// These are sparse, and so the bit positions are assigned manually.
|
||||
const (
|
||||
// On AMD, EDX[24:23] | EDX[17:12] | EDX[9:0] are duplicate features
|
||||
// also defined in block 1 (in identical bit positions). Those features
|
||||
// are not listed here.
|
||||
block6DuplicateMask = 0x183f3ff
|
||||
|
||||
X86FeatureSYSCALL Feature = 6*32 + 11
|
||||
X86FeatureNX Feature = 6*32 + 20
|
||||
X86FeatureMMXEXT Feature = 6*32 + 22
|
||||
X86FeatureFXSR_OPT Feature = 6*32 + 25
|
||||
X86FeatureGBPAGES Feature = 6*32 + 26
|
||||
X86FeatureRDTSCP Feature = 6*32 + 27
|
||||
X86FeatureLM Feature = 6*32 + 29
|
||||
X86Feature3DNOWEXT Feature = 6*32 + 30
|
||||
X86Feature3DNOW Feature = 6*32 + 31
|
||||
)
|
||||
|
||||
// Block 7 constants are the extended features bits in
|
||||
// CPUID.(EAX=07H,ECX=0):EDX.
|
||||
const (
|
||||
_ Feature = 7*32 + iota // edx bit 0 is reserved.
|
||||
_ // edx bit 1 is reserved.
|
||||
X86FeatureAVX512_4VNNIW
|
||||
X86FeatureAVX512_4FMAPS
|
||||
X86FeatureFSRM
|
||||
_ // edx bit 5 is not used in Linux.
|
||||
_ // edx bit 6 is reserved.
|
||||
_ // edx bit 7 is reserved.
|
||||
X86FeatureAVX512_VP2INTERSECT
|
||||
X86FeatureSRBDS_CTRL
|
||||
X86FeatureMD_CLEAR
|
||||
X86FeatureRTM_ALWAYS_ABORT
|
||||
_ // edx bit 12 is reserved.
|
||||
X86FeatureTSX_FORCE_ABORT
|
||||
X86FeatureSERIALIZE
|
||||
X86FeatureHYBRID_CPU
|
||||
X86FeatureTSXLDTRK
|
||||
_ // edx bit 17 is reserved.
|
||||
X86FeaturePCONFIG
|
||||
X86FeatureARCH_LBR
|
||||
X86FeatureIBT
|
||||
_ // edx bit 21 is reserved.
|
||||
X86FeatureAMX_BF16
|
||||
X86FeatureAVX512_FP16
|
||||
X86FeatureAMX_TILE
|
||||
X86FeatureAMX_INT8
|
||||
X86FeatureSPEC_CTRL
|
||||
X86FeatureINTEL_STIBP
|
||||
X86FeatureFLUSH_L1D
|
||||
X86FeatureARCH_CAPABILITIES
|
||||
X86FeatureCORE_CAPABILITIES
|
||||
X86FeatureSPEC_CTRL_SSBD
|
||||
)
|
||||
|
||||
// These are the extended floating point state features. They are used to
|
||||
// enumerate floating point features in XCR0, XSTATE_BV, etc.
|
||||
const (
|
||||
XSAVEFeatureX87 = 1 << 0
|
||||
XSAVEFeatureSSE = 1 << 1
|
||||
XSAVEFeatureAVX = 1 << 2
|
||||
XSAVEFeatureBNDREGS = 1 << 3
|
||||
XSAVEFeatureBNDCSR = 1 << 4
|
||||
XSAVEFeatureAVX512op = 1 << 5
|
||||
XSAVEFeatureAVX512zmm0 = 1 << 6
|
||||
XSAVEFeatureAVX512zmm16 = 1 << 7
|
||||
XSAVEFeaturePKRU = 1 << 9
|
||||
)
|
||||
|
||||
// allFeatures is the set of allFeatures.
|
||||
//
|
||||
// These match names used in arch/x86/kernel/cpu/capflags.c.
|
||||
var allFeatures = map[Feature]allFeatureInfo{
|
||||
// Block 0.
|
||||
X86FeatureSSE3: {"pni", true},
|
||||
X86FeaturePCLMULDQ: {"pclmulqdq", true},
|
||||
X86FeatureDTES64: {"dtes64", true},
|
||||
X86FeatureMONITOR: {"monitor", true},
|
||||
X86FeatureDSCPL: {"ds_cpl", true},
|
||||
X86FeatureVMX: {"vmx", true},
|
||||
X86FeatureSMX: {"smx", true},
|
||||
X86FeatureEST: {"est", true},
|
||||
X86FeatureTM2: {"tm2", true},
|
||||
X86FeatureSSSE3: {"ssse3", true},
|
||||
X86FeatureCNXTID: {"cid", true},
|
||||
X86FeatureSDBG: {"sdbg", true},
|
||||
X86FeatureFMA: {"fma", true},
|
||||
X86FeatureCX16: {"cx16", true},
|
||||
X86FeatureXTPR: {"xtpr", true},
|
||||
X86FeaturePDCM: {"pdcm", true},
|
||||
X86FeaturePCID: {"pcid", true},
|
||||
X86FeatureDCA: {"dca", true},
|
||||
X86FeatureSSE4_1: {"sse4_1", true},
|
||||
X86FeatureSSE4_2: {"sse4_2", true},
|
||||
X86FeatureX2APIC: {"x2apic", true},
|
||||
X86FeatureMOVBE: {"movbe", true},
|
||||
X86FeaturePOPCNT: {"popcnt", true},
|
||||
X86FeatureTSCD: {"tsc_deadline_timer", true},
|
||||
X86FeatureAES: {"aes", true},
|
||||
X86FeatureXSAVE: {"xsave", true},
|
||||
X86FeatureAVX: {"avx", true},
|
||||
X86FeatureF16C: {"f16c", true},
|
||||
X86FeatureRDRAND: {"rdrand", true},
|
||||
X86FeatureHypervisor: {"hypervisor", true},
|
||||
X86FeatureOSXSAVE: {"osxsave", false},
|
||||
|
||||
// Block 1.
|
||||
X86FeatureFPU: {"fpu", true},
|
||||
X86FeatureVME: {"vme", true},
|
||||
X86FeatureDE: {"de", true},
|
||||
X86FeaturePSE: {"pse", true},
|
||||
X86FeatureTSC: {"tsc", true},
|
||||
X86FeatureMSR: {"msr", true},
|
||||
X86FeaturePAE: {"pae", true},
|
||||
X86FeatureMCE: {"mce", true},
|
||||
X86FeatureCX8: {"cx8", true},
|
||||
X86FeatureAPIC: {"apic", true},
|
||||
X86FeatureSEP: {"sep", true},
|
||||
X86FeatureMTRR: {"mtrr", true},
|
||||
X86FeaturePGE: {"pge", true},
|
||||
X86FeatureMCA: {"mca", true},
|
||||
X86FeatureCMOV: {"cmov", true},
|
||||
X86FeaturePAT: {"pat", true},
|
||||
X86FeaturePSE36: {"pse36", true},
|
||||
X86FeaturePSN: {"pn", true},
|
||||
X86FeatureCLFSH: {"clflush", true},
|
||||
X86FeatureDS: {"dts", true},
|
||||
X86FeatureACPI: {"acpi", true},
|
||||
X86FeatureMMX: {"mmx", true},
|
||||
X86FeatureFXSR: {"fxsr", true},
|
||||
X86FeatureSSE: {"sse", true},
|
||||
X86FeatureSSE2: {"sse2", true},
|
||||
X86FeatureSS: {"ss", true},
|
||||
X86FeatureHTT: {"ht", true},
|
||||
X86FeatureTM: {"tm", true},
|
||||
X86FeatureIA64: {"ia64", true},
|
||||
X86FeaturePBE: {"pbe", true},
|
||||
|
||||
// Block 2.
|
||||
X86FeatureFSGSBase: {"fsgsbase", true},
|
||||
X86FeatureTSC_ADJUST: {"tsc_adjust", true},
|
||||
X86FeatureBMI1: {"bmi1", true},
|
||||
X86FeatureHLE: {"hle", true},
|
||||
X86FeatureAVX2: {"avx2", true},
|
||||
X86FeatureSMEP: {"smep", true},
|
||||
X86FeatureBMI2: {"bmi2", true},
|
||||
X86FeatureERMS: {"erms", true},
|
||||
X86FeatureINVPCID: {"invpcid", true},
|
||||
X86FeatureRTM: {"rtm", true},
|
||||
X86FeatureCQM: {"cqm", true},
|
||||
X86FeatureMPX: {"mpx", true},
|
||||
X86FeatureRDT: {"rdt_a", true},
|
||||
X86FeatureAVX512F: {"avx512f", true},
|
||||
X86FeatureAVX512DQ: {"avx512dq", true},
|
||||
X86FeatureRDSEED: {"rdseed", true},
|
||||
X86FeatureADX: {"adx", true},
|
||||
X86FeatureSMAP: {"smap", true},
|
||||
X86FeatureCLWB: {"clwb", true},
|
||||
X86FeatureAVX512PF: {"avx512pf", true},
|
||||
X86FeatureAVX512ER: {"avx512er", true},
|
||||
X86FeatureAVX512CD: {"avx512cd", true},
|
||||
X86FeatureSHA: {"sha_ni", true},
|
||||
X86FeatureAVX512BW: {"avx512bw", true},
|
||||
X86FeatureAVX512VL: {"avx512vl", true},
|
||||
X86FeatureFDP_EXCPTN_ONLY: {"fdp_excptn_only", false},
|
||||
X86FeatureFPCSDS: {"fpcsds", false},
|
||||
X86FeatureIPT: {"ipt", false},
|
||||
X86FeatureCLFLUSHOPT: {"clfushopt", false},
|
||||
|
||||
// Block 3.
|
||||
X86FeatureAVX512VBMI: {"avx512vbmi", true},
|
||||
X86FeatureUMIP: {"umip", true},
|
||||
X86FeaturePKU: {"pku", true},
|
||||
X86FeatureOSPKE: {"ospke", true},
|
||||
X86FeatureWAITPKG: {"waitpkg", true},
|
||||
X86FeatureAVX512_VBMI2: {"avx512_vbmi2", true},
|
||||
X86FeatureGFNI: {"gfni", true},
|
||||
X86FeatureCET_SS: {"cet_ss", false},
|
||||
X86FeatureVAES: {"vaes", true},
|
||||
X86FeatureVPCLMULQDQ: {"vpclmulqdq", true},
|
||||
X86FeatureAVX512_VNNI: {"avx512_vnni", true},
|
||||
X86FeatureAVX512_BITALG: {"avx512_bitalg", true},
|
||||
X86FeatureTME: {"tme", true},
|
||||
X86FeatureAVX512_VPOPCNTDQ: {"avx512_vpopcntdq", true},
|
||||
X86FeatureLA57: {"la57", true},
|
||||
X86FeatureRDPID: {"rdpid", true},
|
||||
X86FeatureCLDEMOTE: {"cldemote", true},
|
||||
X86FeatureMOVDIRI: {"movdiri", true},
|
||||
X86FeatureMOVDIR64B: {"movdir64b", true},
|
||||
X86FeaturePREFETCHWT1: {"prefetchwt1", false},
|
||||
|
||||
// Block 4.
|
||||
X86FeatureXSAVEOPT: {"xsaveopt", true},
|
||||
X86FeatureXSAVEC: {"xsavec", true},
|
||||
X86FeatureXGETBV1: {"xgetbv1", true},
|
||||
X86FeatureXSAVES: {"xsaves", true},
|
||||
|
||||
// Block 5.
|
||||
X86FeatureLAHF64: {"lahf_lm", true}, // LAHF/SAHF in long mode.
|
||||
X86FeatureCMP_LEGACY: {"cmp_legacy", true},
|
||||
X86FeatureSVM: {"svm", true},
|
||||
X86FeatureEXTAPIC: {"extapic", true},
|
||||
X86FeatureCR8_LEGACY: {"cr8_legacy", true},
|
||||
X86FeatureLZCNT: {"abm", true}, // Advanced bit manipulation.
|
||||
X86FeatureSSE4A: {"sse4a", true},
|
||||
X86FeatureMISALIGNSSE: {"misalignsse", true},
|
||||
X86FeaturePREFETCHW: {"3dnowprefetch", true},
|
||||
X86FeatureOSVW: {"osvw", true},
|
||||
X86FeatureIBS: {"ibs", true},
|
||||
X86FeatureXOP: {"xop", true},
|
||||
X86FeatureSKINIT: {"skinit", true},
|
||||
X86FeatureWDT: {"wdt", true},
|
||||
X86FeatureLWP: {"lwp", true},
|
||||
X86FeatureFMA4: {"fma4", true},
|
||||
X86FeatureTCE: {"tce", true},
|
||||
X86FeatureTBM: {"tbm", true},
|
||||
X86FeatureTOPOLOGY: {"topoext", true},
|
||||
X86FeaturePERFCTR_CORE: {"perfctr_core", true},
|
||||
X86FeaturePERFCTR_NB: {"perfctr_nb", true},
|
||||
X86FeatureBPEXT: {"bpext", true},
|
||||
X86FeaturePERFCTR_TSC: {"ptsc", true},
|
||||
X86FeaturePERFCTR_LLC: {"perfctr_llc", true},
|
||||
X86FeatureMWAITX: {"mwaitx", true},
|
||||
X86FeatureADMSKEXTN: {"ad_mask_extn", false},
|
||||
|
||||
// Block 6.
|
||||
X86FeatureSYSCALL: {"syscall", true},
|
||||
X86FeatureNX: {"nx", true},
|
||||
X86FeatureMMXEXT: {"mmxext", true},
|
||||
X86FeatureFXSR_OPT: {"fxsr_opt", true},
|
||||
X86FeatureGBPAGES: {"pdpe1gb", true},
|
||||
X86FeatureRDTSCP: {"rdtscp", true},
|
||||
X86FeatureLM: {"lm", true},
|
||||
X86Feature3DNOWEXT: {"3dnowext", true},
|
||||
X86Feature3DNOW: {"3dnow", true},
|
||||
|
||||
// Block 7.
|
||||
X86FeatureAVX512_4VNNIW: {"avx512_4vnniw", true},
|
||||
X86FeatureAVX512_4FMAPS: {"avx512_4fmaps", true},
|
||||
X86FeatureFSRM: {"fsrm", true},
|
||||
X86FeatureAVX512_VP2INTERSECT: {"avx512_vp2intersect", true},
|
||||
X86FeatureSRBDS_CTRL: {"srbds_ctrl", false},
|
||||
X86FeatureMD_CLEAR: {"md_clear", true},
|
||||
X86FeatureRTM_ALWAYS_ABORT: {"rtm_always_abort", false},
|
||||
X86FeatureTSX_FORCE_ABORT: {"tsx_force_abort", false},
|
||||
X86FeatureSERIALIZE: {"serialize", true},
|
||||
X86FeatureHYBRID_CPU: {"hybrid_cpu", false},
|
||||
X86FeatureTSXLDTRK: {"tsxldtrk", true},
|
||||
X86FeaturePCONFIG: {"pconfig", true},
|
||||
X86FeatureARCH_LBR: {"arch_lbr", true},
|
||||
X86FeatureIBT: {"ibt", true},
|
||||
X86FeatureAMX_BF16: {"amx_bf16", true},
|
||||
X86FeatureAVX512_FP16: {"avx512_fp16", true},
|
||||
X86FeatureAMX_TILE: {"amx_tile", true},
|
||||
X86FeatureAMX_INT8: {"amx_int8", true},
|
||||
X86FeatureSPEC_CTRL: {"spec_ctrl", false},
|
||||
X86FeatureINTEL_STIBP: {"intel_stibp", false},
|
||||
X86FeatureFLUSH_L1D: {"flush_l1d", true},
|
||||
X86FeatureARCH_CAPABILITIES: {"arch_capabilities", true},
|
||||
X86FeatureCORE_CAPABILITIES: {"core_capabilities", false},
|
||||
X86FeatureSPEC_CTRL_SSBD: {"spec_ctrl_ssbd", false},
|
||||
}
|
||||
|
||||
// linuxBlockOrder defines the order in which linux organizes the feature
|
||||
// blocks. Linux also tracks feature bits in 32-bit blocks, but in an order
|
||||
// which doesn't match well here, so for the /proc/cpuinfo generation we simply
|
||||
// re-map the blocks to Linux's ordering and then go through the bits in each
|
||||
// block.
|
||||
var linuxBlockOrder = []block{1, 6, 0, 5, 2, 4, 3, 7}
|
||||
|
||||
func archFlagOrder(fn func(Feature)) {
|
||||
for _, b := range linuxBlockOrder {
|
||||
for i := 0; i < blockSize; i++ {
|
||||
f := featureID(b, i)
|
||||
if _, ok := allFeatures[f]; ok {
|
||||
fn(f)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
147
vendor/gvisor.dev/gvisor/pkg/cpuid/features_arm64.go
vendored
Normal file
147
vendor/gvisor.dev/gvisor/pkg/cpuid/features_arm64.go
vendored
Normal file
@@ -0,0 +1,147 @@
|
||||
// Copyright 2020 The gVisor Authors.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
//go:build arm64
|
||||
// +build arm64
|
||||
|
||||
package cpuid
|
||||
|
||||
const (
|
||||
// ARM64FeatureFP indicates support for single and double precision
|
||||
// float point types.
|
||||
ARM64FeatureFP Feature = iota
|
||||
|
||||
// ARM64FeatureASIMD indicates support for Advanced SIMD with single
|
||||
// and double precision float point arithmetic.
|
||||
ARM64FeatureASIMD
|
||||
|
||||
// ARM64FeatureEVTSTRM indicates support for the generic timer
|
||||
// configured to generate events at a frequency of approximately
|
||||
// 100KHz.
|
||||
ARM64FeatureEVTSTRM
|
||||
|
||||
// ARM64FeatureAES indicates support for AES instructions
|
||||
// (AESE/AESD/AESMC/AESIMC).
|
||||
ARM64FeatureAES
|
||||
|
||||
// ARM64FeaturePMULL indicates support for AES instructions
|
||||
// (PMULL/PMULL2).
|
||||
ARM64FeaturePMULL
|
||||
|
||||
// ARM64FeatureSHA1 indicates support for SHA1 instructions
|
||||
// (SHA1C/SHA1P/SHA1M etc).
|
||||
ARM64FeatureSHA1
|
||||
|
||||
// ARM64FeatureSHA2 indicates support for SHA2 instructions
|
||||
// (SHA256H/SHA256H2/SHA256SU0 etc).
|
||||
ARM64FeatureSHA2
|
||||
|
||||
// ARM64FeatureCRC32 indicates support for CRC32 instructions
|
||||
// (CRC32B/CRC32H/CRC32W etc).
|
||||
ARM64FeatureCRC32
|
||||
|
||||
// ARM64FeatureATOMICS indicates support for atomic instructions
|
||||
// (LDADD/LDCLR/LDEOR/LDSET etc).
|
||||
ARM64FeatureATOMICS
|
||||
|
||||
// ARM64FeatureFPHP indicates support for half precision float point
|
||||
// arithmetic.
|
||||
ARM64FeatureFPHP
|
||||
|
||||
// ARM64FeatureASIMDHP indicates support for ASIMD with half precision
|
||||
// float point arithmetic.
|
||||
ARM64FeatureASIMDHP
|
||||
|
||||
// ARM64FeatureCPUID indicates support for EL0 access to certain ID
|
||||
// registers is available.
|
||||
ARM64FeatureCPUID
|
||||
|
||||
// ARM64FeatureASIMDRDM indicates support for SQRDMLAH and SQRDMLSH
|
||||
// instructions.
|
||||
ARM64FeatureASIMDRDM
|
||||
|
||||
// ARM64FeatureJSCVT indicates support for the FJCVTZS instruction.
|
||||
ARM64FeatureJSCVT
|
||||
|
||||
// ARM64FeatureFCMA indicates support for the FCMLA and FCADD
|
||||
// instructions.
|
||||
ARM64FeatureFCMA
|
||||
|
||||
// ARM64FeatureLRCPC indicates support for the LDAPRB/LDAPRH/LDAPR
|
||||
// instructions.
|
||||
ARM64FeatureLRCPC
|
||||
|
||||
// ARM64FeatureDCPOP indicates support for DC instruction (DC CVAP).
|
||||
ARM64FeatureDCPOP
|
||||
|
||||
// ARM64FeatureSHA3 indicates support for SHA3 instructions
|
||||
// (EOR3/RAX1/XAR/BCAX).
|
||||
ARM64FeatureSHA3
|
||||
|
||||
// ARM64FeatureSM3 indicates support for SM3 instructions
|
||||
// (SM3SS1/SM3TT1A/SM3TT1B).
|
||||
ARM64FeatureSM3
|
||||
|
||||
// ARM64FeatureSM4 indicates support for SM4 instructions
|
||||
// (SM4E/SM4EKEY).
|
||||
ARM64FeatureSM4
|
||||
|
||||
// ARM64FeatureASIMDDP indicates support for dot product instructions
|
||||
// (UDOT/SDOT).
|
||||
ARM64FeatureASIMDDP
|
||||
|
||||
// ARM64FeatureSHA512 indicates support for SHA2 instructions
|
||||
// (SHA512H/SHA512H2/SHA512SU0).
|
||||
ARM64FeatureSHA512
|
||||
|
||||
// ARM64FeatureSVE indicates support for Scalable Vector Extension.
|
||||
ARM64FeatureSVE
|
||||
|
||||
// ARM64FeatureASIMDFHM indicates support for FMLAL and FMLSL
|
||||
// instructions.
|
||||
ARM64FeatureASIMDFHM
|
||||
)
|
||||
|
||||
var allFeatures = map[Feature]allFeatureInfo{
|
||||
ARM64FeatureFP: {"fp", true},
|
||||
ARM64FeatureASIMD: {"asimd", true},
|
||||
ARM64FeatureEVTSTRM: {"evtstrm", true},
|
||||
ARM64FeatureAES: {"aes", true},
|
||||
ARM64FeaturePMULL: {"pmull", true},
|
||||
ARM64FeatureSHA1: {"sha1", true},
|
||||
ARM64FeatureSHA2: {"sha2", true},
|
||||
ARM64FeatureCRC32: {"crc32", true},
|
||||
ARM64FeatureATOMICS: {"atomics", true},
|
||||
ARM64FeatureFPHP: {"fphp", true},
|
||||
ARM64FeatureASIMDHP: {"asimdhp", true},
|
||||
ARM64FeatureCPUID: {"cpuid", true},
|
||||
ARM64FeatureASIMDRDM: {"asimdrdm", true},
|
||||
ARM64FeatureJSCVT: {"jscvt", true},
|
||||
ARM64FeatureFCMA: {"fcma", true},
|
||||
ARM64FeatureLRCPC: {"lrcpc", true},
|
||||
ARM64FeatureDCPOP: {"dcpop", true},
|
||||
ARM64FeatureSHA3: {"sha3", true},
|
||||
ARM64FeatureSM3: {"sm3", true},
|
||||
ARM64FeatureSM4: {"sm4", true},
|
||||
ARM64FeatureASIMDDP: {"asimddp", true},
|
||||
ARM64FeatureSHA512: {"sha512", true},
|
||||
ARM64FeatureSVE: {"sve", true},
|
||||
ARM64FeatureASIMDFHM: {"asimdfhm", true},
|
||||
}
|
||||
|
||||
func archFlagOrder(fn func(Feature)) {
|
||||
for i := 0; i < len(allFeatures); i++ {
|
||||
fn(Feature(i))
|
||||
}
|
||||
}
|
||||
229
vendor/gvisor.dev/gvisor/pkg/cpuid/native_amd64.go
vendored
Normal file
229
vendor/gvisor.dev/gvisor/pkg/cpuid/native_amd64.go
vendored
Normal file
@@ -0,0 +1,229 @@
|
||||
// Copyright 2019 The gVisor Authors.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
//go:build amd64
|
||||
// +build amd64
|
||||
|
||||
package cpuid
|
||||
|
||||
import (
|
||||
"io/ioutil"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"gvisor.dev/gvisor/pkg/log"
|
||||
)
|
||||
|
||||
// cpuididFunction is a useful type wrapper. The format is eax | (ecx << 32).
|
||||
type cpuidFunction uint64
|
||||
|
||||
func (f cpuidFunction) eax() uint32 {
|
||||
return uint32(f)
|
||||
}
|
||||
|
||||
func (f cpuidFunction) ecx() uint32 {
|
||||
return uint32(f >> 32)
|
||||
}
|
||||
|
||||
// The constants below are the lower or "standard" cpuid functions, ordered as
|
||||
// defined by the hardware. Note that these may not be included in the standard
|
||||
// set of functions that we are allowed to execute, which are filtered in the
|
||||
// Native.Query function defined below.
|
||||
const (
|
||||
vendorID cpuidFunction = 0x0 // Returns vendor ID and largest standard function.
|
||||
featureInfo cpuidFunction = 0x1 // Returns basic feature bits and processor signature.
|
||||
intelCacheDescriptors cpuidFunction = 0x2 // Returns list of cache descriptors. Intel only.
|
||||
intelSerialNumber cpuidFunction = 0x3 // Returns processor serial number (obsolete on new hardware). Intel only.
|
||||
intelDeterministicCacheParams cpuidFunction = 0x4 // Returns deterministic cache information. Intel only.
|
||||
monitorMwaitParams cpuidFunction = 0x5 // Returns information about monitor/mwait instructions.
|
||||
powerParams cpuidFunction = 0x6 // Returns information about power management and thermal sensors.
|
||||
extendedFeatureInfo cpuidFunction = 0x7 // Returns extended feature bits.
|
||||
_ // Function 0x8 is reserved.
|
||||
intelDCAParams cpuidFunction = 0x9 // Returns direct cache access information. Intel only.
|
||||
intelPMCInfo cpuidFunction = 0xa // Returns information about performance monitoring features. Intel only.
|
||||
intelX2APICInfo cpuidFunction = 0xb // Returns core/logical processor topology. Intel only.
|
||||
_ // Function 0xc is reserved.
|
||||
xSaveInfo cpuidFunction = 0xd // Returns information about extended state management.
|
||||
xSaveInfoSub cpuidFunction = 0xd | (0x1 << 32) // Returns information about extended state management (Sub-leaf).
|
||||
)
|
||||
|
||||
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.
|
||||
)
|
||||
|
||||
var allowedBasicFunctions = [...]bool{
|
||||
vendorID: true,
|
||||
featureInfo: true,
|
||||
extendedFeatureInfo: true,
|
||||
intelCacheDescriptors: true,
|
||||
intelDeterministicCacheParams: true,
|
||||
xSaveInfo: true,
|
||||
}
|
||||
|
||||
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,
|
||||
}
|
||||
|
||||
// Function executes a CPUID function.
|
||||
//
|
||||
// This is typically the native function or a Static definition.
|
||||
type Function interface {
|
||||
Query(In) Out
|
||||
}
|
||||
|
||||
// Native is a native Function.
|
||||
//
|
||||
// This implements Function.
|
||||
type Native struct{}
|
||||
|
||||
// In is input to the Query function.
|
||||
//
|
||||
// +stateify savable
|
||||
type In struct {
|
||||
Eax uint32
|
||||
Ecx uint32
|
||||
}
|
||||
|
||||
// normalize drops irrelevant Ecx values.
|
||||
func (i *In) normalize() {
|
||||
switch cpuidFunction(i.Eax) {
|
||||
case vendorID, featureInfo, intelCacheDescriptors, extendedFunctionInfo, extendedFeatures:
|
||||
i.Ecx = 0 // Ignore.
|
||||
case processorBrandString2, processorBrandString3, processorBrandString4, l1CacheAndTLBInfo, l2CacheInfo:
|
||||
i.Ecx = 0 // Ignore.
|
||||
case intelDeterministicCacheParams, extendedFeatureInfo:
|
||||
// Preserve i.Ecx.
|
||||
}
|
||||
}
|
||||
|
||||
// Out is output from the Query function.
|
||||
//
|
||||
// +stateify savable
|
||||
type Out struct {
|
||||
Eax uint32
|
||||
Ebx uint32
|
||||
Ecx uint32
|
||||
Edx uint32
|
||||
}
|
||||
|
||||
// native is the native Query function.
|
||||
func native(In) Out
|
||||
|
||||
// Query executes CPUID natively.
|
||||
//
|
||||
// This implements Function.
|
||||
//
|
||||
//go:nosplit
|
||||
func (*Native) Query(in In) Out {
|
||||
if int(in.Eax) < len(allowedBasicFunctions) && allowedBasicFunctions[in.Eax] {
|
||||
return native(in)
|
||||
} else if in.Eax >= uint32(extendedStart) {
|
||||
if l := int(in.Eax - uint32(extendedStart)); l < len(allowedExtendedFunctions) && allowedExtendedFunctions[l] {
|
||||
return native(in)
|
||||
}
|
||||
}
|
||||
return Out{} // All zeros.
|
||||
}
|
||||
|
||||
// query is a internal wrapper.
|
||||
//
|
||||
//go:nosplit
|
||||
func (fs FeatureSet) query(fn cpuidFunction) (uint32, uint32, uint32, uint32) {
|
||||
out := fs.Query(In{Eax: fn.eax(), Ecx: fn.ecx()})
|
||||
return out.Eax, out.Ebx, out.Ecx, out.Edx
|
||||
}
|
||||
|
||||
var hostFeatureSet FeatureSet
|
||||
|
||||
// HostFeatureSet returns a host CPUID.
|
||||
//
|
||||
//go:nosplit
|
||||
func HostFeatureSet() FeatureSet {
|
||||
return hostFeatureSet
|
||||
}
|
||||
|
||||
var (
|
||||
// cpuFreqMHz is the native CPU frequency.
|
||||
cpuFreqMHz float64
|
||||
)
|
||||
|
||||
// Reads max cpu frequency from host /proc/cpuinfo. Must run before syscall
|
||||
// filter installation. This value is used to create the fake /proc/cpuinfo
|
||||
// from a FeatureSet.
|
||||
func readMaxCPUFreq() {
|
||||
cpuinfob, err := ioutil.ReadFile("/proc/cpuinfo")
|
||||
if err != nil {
|
||||
// Leave it as 0... the VDSO bails out in the same way.
|
||||
log.Warningf("Could not read /proc/cpuinfo: %v", err)
|
||||
return
|
||||
}
|
||||
cpuinfo := string(cpuinfob)
|
||||
|
||||
// We get the value straight from host /proc/cpuinfo. On machines with
|
||||
// frequency scaling enabled, this will only get the current value
|
||||
// which will likely be inaccurate. This is fine on machines with
|
||||
// frequency scaling disabled.
|
||||
for _, line := range strings.Split(cpuinfo, "\n") {
|
||||
if strings.Contains(line, "cpu MHz") {
|
||||
splitMHz := strings.Split(line, ":")
|
||||
if len(splitMHz) < 2 {
|
||||
log.Warningf("Could not read /proc/cpuinfo: malformed cpu MHz line")
|
||||
return
|
||||
}
|
||||
|
||||
// If there was a problem, leave cpuFreqMHz as 0.
|
||||
var err error
|
||||
cpuFreqMHz, err = strconv.ParseFloat(strings.TrimSpace(splitMHz[1]), 64)
|
||||
if err != nil {
|
||||
log.Warningf("Could not parse cpu MHz value %v: %v", splitMHz[1], err)
|
||||
cpuFreqMHz = 0
|
||||
return
|
||||
}
|
||||
return
|
||||
}
|
||||
}
|
||||
log.Warningf("Could not parse /proc/cpuinfo, it is empty or does not contain cpu MHz")
|
||||
|
||||
}
|
||||
|
||||
// xgetbv reads an extended control register.
|
||||
func xgetbv(reg uintptr) uint64
|
||||
|
||||
// archInitialize initializes hostFeatureSet.
|
||||
func archInitialize() {
|
||||
hostFeatureSet = FeatureSet{
|
||||
Function: &Native{},
|
||||
}.Fixed()
|
||||
|
||||
readMaxCPUFreq()
|
||||
initHWCap()
|
||||
}
|
||||
38
vendor/gvisor.dev/gvisor/pkg/cpuid/native_amd64.s
vendored
Normal file
38
vendor/gvisor.dev/gvisor/pkg/cpuid/native_amd64.s
vendored
Normal file
@@ -0,0 +1,38 @@
|
||||
// Copyright 2018 The gVisor Authors.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#include "textflag.h"
|
||||
|
||||
TEXT ·native(SB),NOSPLIT|NOFRAME,$0-24
|
||||
MOVL arg_Eax+0(FP), AX
|
||||
MOVL arg_Ecx+4(FP), CX
|
||||
CPUID
|
||||
MOVL AX, ret_Eax+8(FP)
|
||||
MOVL BX, ret_Ebx+12(FP)
|
||||
MOVL CX, ret_Ecx+16(FP)
|
||||
MOVL DX, ret_Edx+20(FP)
|
||||
RET
|
||||
|
||||
// xgetbv reads an extended control register.
|
||||
//
|
||||
// The code corresponds to:
|
||||
//
|
||||
// xgetbv
|
||||
//
|
||||
TEXT ·xgetbv(SB),NOSPLIT|NOFRAME,$0-16
|
||||
MOVQ reg+0(FP), CX
|
||||
BYTE $0x0f; BYTE $0x01; BYTE $0xd0;
|
||||
MOVL AX, ret+8(FP)
|
||||
MOVL DX, ret+12(FP)
|
||||
RET
|
||||
157
vendor/gvisor.dev/gvisor/pkg/cpuid/native_arm64.go
vendored
Normal file
157
vendor/gvisor.dev/gvisor/pkg/cpuid/native_arm64.go
vendored
Normal file
@@ -0,0 +1,157 @@
|
||||
// Copyright 2019 The gVisor Authors.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
//go:build arm64
|
||||
// +build arm64
|
||||
|
||||
package cpuid
|
||||
|
||||
import (
|
||||
"io/ioutil"
|
||||
"runtime"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"gvisor.dev/gvisor/pkg/log"
|
||||
)
|
||||
|
||||
// hostFeatureSet is initialized at startup.
|
||||
//
|
||||
// This is copied for HostFeatureSet, below.
|
||||
var hostFeatureSet FeatureSet
|
||||
|
||||
// HostFeatureSet returns a copy of the host FeatureSet.
|
||||
func HostFeatureSet() FeatureSet {
|
||||
return hostFeatureSet
|
||||
}
|
||||
|
||||
// Fixed returns the same feature set.
|
||||
func (fs FeatureSet) Fixed() FeatureSet {
|
||||
return fs
|
||||
}
|
||||
|
||||
// Reads CPU information from host /proc/cpuinfo.
|
||||
//
|
||||
// Must run before syscall filter installation. This value is used to create
|
||||
// the fake /proc/cpuinfo from a FeatureSet.
|
||||
func initCPUInfo() {
|
||||
if runtime.GOOS != "linux" {
|
||||
// Don't try to read Linux-specific /proc files or
|
||||
// warn about them not existing.
|
||||
return
|
||||
}
|
||||
cpuinfob, err := ioutil.ReadFile("/proc/cpuinfo")
|
||||
if err != nil {
|
||||
// Leave everything at 0, nothing can be done.
|
||||
log.Warningf("Could not read /proc/cpuinfo: %v", err)
|
||||
return
|
||||
}
|
||||
cpuinfo := string(cpuinfob)
|
||||
|
||||
// We get the value straight from host /proc/cpuinfo.
|
||||
for _, line := range strings.Split(cpuinfo, "\n") {
|
||||
switch {
|
||||
case strings.Contains(line, "BogoMIPS"):
|
||||
splitMHz := strings.Split(line, ":")
|
||||
if len(splitMHz) < 2 {
|
||||
log.Warningf("Could not read /proc/cpuinfo: malformed BogoMIPS")
|
||||
break
|
||||
}
|
||||
|
||||
// If there was a problem, leave cpuFreqMHz as 0.
|
||||
var err error
|
||||
hostFeatureSet.cpuFreqMHz, err = strconv.ParseFloat(strings.TrimSpace(splitMHz[1]), 64)
|
||||
if err != nil {
|
||||
hostFeatureSet.cpuFreqMHz = 0.0
|
||||
log.Warningf("Could not parse BogoMIPS value %v: %v", splitMHz[1], err)
|
||||
}
|
||||
case strings.Contains(line, "CPU implementer"):
|
||||
splitImpl := strings.Split(line, ":")
|
||||
if len(splitImpl) < 2 {
|
||||
log.Warningf("Could not read /proc/cpuinfo: malformed CPU implementer")
|
||||
break
|
||||
}
|
||||
|
||||
// If there was a problem, leave cpuImplHex as 0.
|
||||
var err error
|
||||
hostFeatureSet.cpuImplHex, err = strconv.ParseUint(strings.TrimSpace(splitImpl[1]), 0, 64)
|
||||
if err != nil {
|
||||
hostFeatureSet.cpuImplHex = 0
|
||||
log.Warningf("Could not parse CPU implementer value %v: %v", splitImpl[1], err)
|
||||
}
|
||||
case strings.Contains(line, "CPU architecture"):
|
||||
splitArch := strings.Split(line, ":")
|
||||
if len(splitArch) < 2 {
|
||||
log.Warningf("Could not read /proc/cpuinfo: malformed CPU architecture")
|
||||
break
|
||||
}
|
||||
|
||||
// If there was a problem, leave cpuArchDec as 0.
|
||||
var err error
|
||||
hostFeatureSet.cpuArchDec, err = strconv.ParseUint(strings.TrimSpace(splitArch[1]), 0, 64)
|
||||
if err != nil {
|
||||
hostFeatureSet.cpuArchDec = 0
|
||||
log.Warningf("Could not parse CPU architecture value %v: %v", splitArch[1], err)
|
||||
}
|
||||
case strings.Contains(line, "CPU variant"):
|
||||
splitVar := strings.Split(line, ":")
|
||||
if len(splitVar) < 2 {
|
||||
log.Warningf("Could not read /proc/cpuinfo: malformed CPU variant")
|
||||
break
|
||||
}
|
||||
|
||||
// If there was a problem, leave cpuVarHex as 0.
|
||||
var err error
|
||||
hostFeatureSet.cpuVarHex, err = strconv.ParseUint(strings.TrimSpace(splitVar[1]), 0, 64)
|
||||
if err != nil {
|
||||
hostFeatureSet.cpuVarHex = 0
|
||||
log.Warningf("Could not parse CPU variant value %v: %v", splitVar[1], err)
|
||||
}
|
||||
case strings.Contains(line, "CPU part"):
|
||||
splitPart := strings.Split(line, ":")
|
||||
if len(splitPart) < 2 {
|
||||
log.Warningf("Could not read /proc/cpuinfo: malformed CPU part")
|
||||
break
|
||||
}
|
||||
|
||||
// If there was a problem, leave cpuPartHex as 0.
|
||||
var err error
|
||||
hostFeatureSet.cpuPartHex, err = strconv.ParseUint(strings.TrimSpace(splitPart[1]), 0, 64)
|
||||
if err != nil {
|
||||
hostFeatureSet.cpuPartHex = 0
|
||||
log.Warningf("Could not parse CPU part value %v: %v", splitPart[1], err)
|
||||
}
|
||||
case strings.Contains(line, "CPU revision"):
|
||||
splitRev := strings.Split(line, ":")
|
||||
if len(splitRev) < 2 {
|
||||
log.Warningf("Could not read /proc/cpuinfo: malformed CPU revision")
|
||||
break
|
||||
}
|
||||
|
||||
// If there was a problem, leave cpuRevDec as 0.
|
||||
var err error
|
||||
hostFeatureSet.cpuRevDec, err = strconv.ParseUint(strings.TrimSpace(splitRev[1]), 0, 64)
|
||||
if err != nil {
|
||||
hostFeatureSet.cpuRevDec = 0
|
||||
log.Warningf("Could not parse CPU revision value %v: %v", splitRev[1], err)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// archInitialize initializes hostFeatureSet.
|
||||
func archInitialize() {
|
||||
initCPUInfo()
|
||||
initHWCap()
|
||||
}
|
||||
133
vendor/gvisor.dev/gvisor/pkg/cpuid/static_amd64.go
vendored
Normal file
133
vendor/gvisor.dev/gvisor/pkg/cpuid/static_amd64.go
vendored
Normal file
@@ -0,0 +1,133 @@
|
||||
// Copyright 2019 The gVisor Authors.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
//go:build amd64
|
||||
// +build amd64
|
||||
|
||||
package cpuid
|
||||
|
||||
import "context"
|
||||
|
||||
// Static is a static CPUID function.
|
||||
//
|
||||
// +stateify savable
|
||||
type Static map[In]Out
|
||||
|
||||
// Fixed converts the FeatureSet to a fixed set.
|
||||
func (fs FeatureSet) Fixed() FeatureSet {
|
||||
return fs.ToStatic().ToFeatureSet()
|
||||
}
|
||||
|
||||
// ToStatic converts a FeatureSet to a Static function.
|
||||
//
|
||||
// You can create a new static feature set as:
|
||||
//
|
||||
// fs := otherFeatureSet.ToStatic().ToFeatureSet()
|
||||
func (fs FeatureSet) ToStatic() Static {
|
||||
s := make(Static)
|
||||
|
||||
// Save all allowed top-level functions.
|
||||
for fn, allowed := range allowedBasicFunctions {
|
||||
if allowed {
|
||||
in := In{Eax: uint32(fn)}
|
||||
s[in] = fs.Query(in)
|
||||
}
|
||||
}
|
||||
|
||||
// Save all allowed extended functions.
|
||||
for fn, allowed := range allowedExtendedFunctions {
|
||||
if allowed {
|
||||
in := In{Eax: uint32(fn) + uint32(extendedStart)}
|
||||
s[in] = fs.Query(in)
|
||||
}
|
||||
}
|
||||
|
||||
// Save all features (may be redundant).
|
||||
for feature := range allFeatures {
|
||||
feature.set(s, fs.HasFeature(feature))
|
||||
}
|
||||
|
||||
// Processor Extended State Enumeration.
|
||||
for i := uint32(0); i < xSaveInfoNumLeaves; i++ {
|
||||
in := In{Eax: uint32(xSaveInfo), Ecx: i}
|
||||
s[in] = fs.Query(in)
|
||||
}
|
||||
|
||||
// Save all cache information.
|
||||
out := fs.Query(In{Eax: uint32(featureInfo)})
|
||||
for i := uint32(0); i < out.Ecx; i++ {
|
||||
in := In{Eax: uint32(intelDeterministicCacheParams), Ecx: i}
|
||||
out := fs.Query(in)
|
||||
s[in] = out
|
||||
if CacheType(out.Eax&0xf) == cacheNull {
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
return s
|
||||
}
|
||||
|
||||
// ToFeatureSet converts a static specification to a FeatureSet.
|
||||
//
|
||||
// This overloads some local values, where required.
|
||||
func (s Static) ToFeatureSet() FeatureSet {
|
||||
// Make a copy.
|
||||
ns := make(Static)
|
||||
for k, v := range s {
|
||||
ns[k] = v
|
||||
}
|
||||
ns.normalize()
|
||||
return FeatureSet{ns, hwCap{}}
|
||||
}
|
||||
|
||||
// afterLoad calls normalize.
|
||||
func (s Static) afterLoad(context.Context) {
|
||||
s.normalize()
|
||||
}
|
||||
|
||||
// normalize normalizes FPU sizes.
|
||||
func (s Static) normalize() {
|
||||
// Override local FPU sizes, which must be fixed.
|
||||
fs := FeatureSet{s, hwCap{}}
|
||||
if fs.HasFeature(X86FeatureXSAVE) {
|
||||
in := In{Eax: uint32(xSaveInfo)}
|
||||
out := s[in]
|
||||
out.Ecx = maxXsaveSize
|
||||
out.Ebx = xsaveSize
|
||||
s[in] = out
|
||||
}
|
||||
}
|
||||
|
||||
// Add adds a feature.
|
||||
func (s Static) Add(feature Feature) Static {
|
||||
feature.set(s, true)
|
||||
return s
|
||||
}
|
||||
|
||||
// Remove removes a feature.
|
||||
func (s Static) Remove(feature Feature) Static {
|
||||
feature.set(s, false)
|
||||
return s
|
||||
}
|
||||
|
||||
// Set implements ChangeableSet.Set.
|
||||
func (s Static) Set(in In, out Out) {
|
||||
s[in] = out
|
||||
}
|
||||
|
||||
// Query implements Function.Query.
|
||||
func (s Static) Query(in In) Out {
|
||||
in.normalize()
|
||||
return s[in]
|
||||
}
|
||||
Reference in New Issue
Block a user