static_amd64.go raw

   1  // Copyright 2019 The gVisor Authors.
   2  //
   3  // Licensed under the Apache License, Version 2.0 (the "License");
   4  // you may not use this file except in compliance with the License.
   5  // You may obtain a copy of the License at
   6  //
   7  //     http://www.apache.org/licenses/LICENSE-2.0
   8  //
   9  // Unless required by applicable law or agreed to in writing, software
  10  // distributed under the License is distributed on an "AS IS" BASIS,
  11  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12  // See the License for the specific language governing permissions and
  13  // limitations under the License.
  14  
  15  //go:build amd64
  16  // +build amd64
  17  
  18  package cpuid
  19  
  20  import "context"
  21  
  22  // Static is a static CPUID function.
  23  //
  24  // +stateify savable
  25  type Static map[In]Out
  26  
  27  // Fixed converts the FeatureSet to a fixed set.
  28  func (fs FeatureSet) Fixed() FeatureSet {
  29  	sfs := fs.ToStatic().ToFeatureSet()
  30  	sfs.hwCap = fs.hwCap
  31  	return sfs
  32  }
  33  
  34  // ToStatic converts a FeatureSet to a Static function.
  35  //
  36  // You can create a new static feature set as:
  37  //
  38  //	fs := otherFeatureSet.ToStatic().ToFeatureSet()
  39  func (fs FeatureSet) ToStatic() Static {
  40  	s := make(Static)
  41  
  42  	// Save all allowed top-level functions.
  43  	for fn, allowed := range allowedBasicFunctions {
  44  		if allowed {
  45  			in := In{Eax: uint32(fn)}
  46  			s[in] = fs.Query(in)
  47  		}
  48  	}
  49  
  50  	// Save all allowed extended functions.
  51  	for fn, allowed := range allowedExtendedFunctions {
  52  		if allowed {
  53  			in := In{Eax: uint32(fn) + uint32(extendedStart)}
  54  			s[in] = fs.Query(in)
  55  		}
  56  	}
  57  
  58  	// Save all features (may be redundant).
  59  	for feature := range allFeatures {
  60  		feature.set(s, fs.HasFeature(feature))
  61  	}
  62  
  63  	// Processor Extended State Enumeration.
  64  	for i := uint32(0); i < xSaveInfoNumLeaves; i++ {
  65  		in := In{Eax: uint32(xSaveInfo), Ecx: i}
  66  		s[in] = fs.Query(in)
  67  	}
  68  
  69  	// Save all cache information.
  70  	out := fs.Query(In{Eax: uint32(featureInfo)})
  71  	for i := uint32(0); i < out.Ecx; i++ {
  72  		in := In{Eax: uint32(intelDeterministicCacheParams), Ecx: i}
  73  		out := fs.Query(in)
  74  		s[in] = out
  75  		if CacheType(out.Eax&0xf) == cacheNull {
  76  			break
  77  		}
  78  	}
  79  
  80  	return s
  81  }
  82  
  83  // ToFeatureSet converts a static specification to a FeatureSet.
  84  //
  85  // This overloads some local values, where required.
  86  func (s Static) ToFeatureSet() FeatureSet {
  87  	// Make a copy.
  88  	ns := make(Static)
  89  	for k, v := range s {
  90  		ns[k] = v
  91  	}
  92  	ns.normalize()
  93  	return FeatureSet{ns, hwCap{}}
  94  }
  95  
  96  // afterLoad calls normalize.
  97  func (s Static) afterLoad(context.Context) {
  98  	s.normalize()
  99  }
 100  
 101  // normalize normalizes FPU sizes.
 102  func (s Static) normalize() {
 103  	// Override local FPU sizes, which must be fixed.
 104  	fs := FeatureSet{s, hwCap{}}
 105  	if fs.HasFeature(X86FeatureXSAVE) {
 106  		in := In{Eax: uint32(xSaveInfo)}
 107  		out := s[in]
 108  		out.Ecx = max(out.Ecx, maxXsaveSize)
 109  		out.Ebx = max(out.Ebx, xsaveSize)
 110  		s[in] = out
 111  	}
 112  }
 113  
 114  // Add adds a feature.
 115  func (s Static) Add(feature Feature) Static {
 116  	feature.set(s, true)
 117  	return s
 118  }
 119  
 120  // Remove removes a feature.
 121  func (s Static) Remove(feature Feature) Static {
 122  	feature.set(s, false)
 123  	return s
 124  }
 125  
 126  // Set implements ChangeableSet.Set.
 127  func (s Static) Set(in In, out Out) {
 128  	s[in] = out
 129  }
 130  
 131  // Query implements Function.Query.
 132  func (s Static) Query(in In) Out {
 133  	in.normalize()
 134  	return s[in]
 135  }
 136