gvisor.dev/gvisor@v0.0.0-20240520182842-f9d4d51c7e0f/pkg/cpuid/static_amd64.go (about)

     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  	return fs.ToStatic().ToFeatureSet()
    30  }
    31  
    32  // ToStatic converts a FeatureSet to a Static function.
    33  //
    34  // You can create a new static feature set as:
    35  //
    36  //	fs := otherFeatureSet.ToStatic().ToFeatureSet()
    37  func (fs FeatureSet) ToStatic() Static {
    38  	s := make(Static)
    39  
    40  	// Save all allowed top-level functions.
    41  	for fn, allowed := range allowedBasicFunctions {
    42  		if allowed {
    43  			in := In{Eax: uint32(fn)}
    44  			s[in] = fs.Query(in)
    45  		}
    46  	}
    47  
    48  	// Save all allowed extended functions.
    49  	for fn, allowed := range allowedExtendedFunctions {
    50  		if allowed {
    51  			in := In{Eax: uint32(fn) + uint32(extendedStart)}
    52  			s[in] = fs.Query(in)
    53  		}
    54  	}
    55  
    56  	// Save all features (may be redundant).
    57  	for feature := range allFeatures {
    58  		feature.set(s, fs.HasFeature(feature))
    59  	}
    60  
    61  	// Processor Extended State Enumeration.
    62  	for i := uint32(0); i < xSaveInfoNumLeaves; i++ {
    63  		in := In{Eax: uint32(xSaveInfo), Ecx: i}
    64  		s[in] = fs.Query(in)
    65  	}
    66  
    67  	// Save all cache information.
    68  	out := fs.Query(In{Eax: uint32(featureInfo)})
    69  	for i := uint32(0); i < out.Ecx; i++ {
    70  		in := In{Eax: uint32(intelDeterministicCacheParams), Ecx: i}
    71  		out := fs.Query(in)
    72  		s[in] = out
    73  		if CacheType(out.Eax&0xf) == cacheNull {
    74  			break
    75  		}
    76  	}
    77  
    78  	return s
    79  }
    80  
    81  // ToFeatureSet converts a static specification to a FeatureSet.
    82  //
    83  // This overloads some local values, where required.
    84  func (s Static) ToFeatureSet() FeatureSet {
    85  	// Make a copy.
    86  	ns := make(Static)
    87  	for k, v := range s {
    88  		ns[k] = v
    89  	}
    90  	ns.normalize()
    91  	return FeatureSet{ns, hwCap{}}
    92  }
    93  
    94  // afterLoad calls normalize.
    95  func (s Static) afterLoad(context.Context) {
    96  	s.normalize()
    97  }
    98  
    99  // normalize normalizes FPU sizes.
   100  func (s Static) normalize() {
   101  	// Override local FPU sizes, which must be fixed.
   102  	fs := FeatureSet{s, hwCap{}}
   103  	if fs.HasFeature(X86FeatureXSAVE) {
   104  		in := In{Eax: uint32(xSaveInfo)}
   105  		out := s[in]
   106  		out.Ecx = maxXsaveSize
   107  		out.Ebx = xsaveSize
   108  		s[in] = out
   109  	}
   110  }
   111  
   112  // Add adds a feature.
   113  func (s Static) Add(feature Feature) Static {
   114  	feature.set(s, true)
   115  	return s
   116  }
   117  
   118  // Remove removes a feature.
   119  func (s Static) Remove(feature Feature) Static {
   120  	feature.set(s, false)
   121  	return s
   122  }
   123  
   124  // Set implements ChangeableSet.Set.
   125  func (s Static) Set(in In, out Out) {
   126  	s[in] = out
   127  }
   128  
   129  // Query implements Function.Query.
   130  func (s Static) Query(in In) Out {
   131  	in.normalize()
   132  	return s[in]
   133  }