// 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 { sfs := fs.ToStatic().ToFeatureSet() sfs.hwCap = fs.hwCap return sfs } // 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 = max(out.Ecx, maxXsaveSize) out.Ebx = max(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] }