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