@@ -120,12 +120,132 @@ static u8 mtrr_default_type(struct kvm_mtrr *mtrr_state)
120
120
return mtrr_state -> deftype & IA32_MTRR_DEF_TYPE_TYPE_MASK ;
121
121
}
122
122
123
+ /*
124
+ * Three terms are used in the following code:
125
+ * - segment, it indicates the address segments covered by fixed MTRRs.
126
+ * - unit, it corresponds to the MSR entry in the segment.
127
+ * - range, a range is covered in one memory cache type.
128
+ */
129
+ struct fixed_mtrr_segment {
130
+ u64 start ;
131
+ u64 end ;
132
+
133
+ int range_shift ;
134
+
135
+ /* the start position in kvm_mtrr.fixed_ranges[]. */
136
+ int range_start ;
137
+ };
138
+
139
+ static struct fixed_mtrr_segment fixed_seg_table [] = {
140
+ /* MSR_MTRRfix64K_00000, 1 unit. 64K fixed mtrr. */
141
+ {
142
+ .start = 0x0 ,
143
+ .end = 0x80000 ,
144
+ .range_shift = 16 , /* 64K */
145
+ .range_start = 0 ,
146
+ },
147
+
148
+ /*
149
+ * MSR_MTRRfix16K_80000 ... MSR_MTRRfix16K_A0000, 2 units,
150
+ * 16K fixed mtrr.
151
+ */
152
+ {
153
+ .start = 0x80000 ,
154
+ .end = 0xc0000 ,
155
+ .range_shift = 14 , /* 16K */
156
+ .range_start = 8 ,
157
+ },
158
+
159
+ /*
160
+ * MSR_MTRRfix4K_C0000 ... MSR_MTRRfix4K_F8000, 8 units,
161
+ * 4K fixed mtrr.
162
+ */
163
+ {
164
+ .start = 0xc0000 ,
165
+ .end = 0x100000 ,
166
+ .range_shift = 12 , /* 12K */
167
+ .range_start = 24 ,
168
+ }
169
+ };
170
+
171
+ /*
172
+ * The size of unit is covered in one MSR, one MSR entry contains
173
+ * 8 ranges so that unit size is always 8 * 2^range_shift.
174
+ */
175
+ static u64 fixed_mtrr_seg_unit_size (int seg )
176
+ {
177
+ return 8 << fixed_seg_table [seg ].range_shift ;
178
+ }
179
+
180
+ static bool fixed_msr_to_seg_unit (u32 msr , int * seg , int * unit )
181
+ {
182
+ switch (msr ) {
183
+ case MSR_MTRRfix64K_00000 :
184
+ * seg = 0 ;
185
+ * unit = 0 ;
186
+ break ;
187
+ case MSR_MTRRfix16K_80000 ... MSR_MTRRfix16K_A0000 :
188
+ * seg = 1 ;
189
+ * unit = msr - MSR_MTRRfix16K_80000 ;
190
+ break ;
191
+ case MSR_MTRRfix4K_C0000 ... MSR_MTRRfix4K_F8000 :
192
+ * seg = 2 ;
193
+ * unit = msr - MSR_MTRRfix4K_C0000 ;
194
+ break ;
195
+ default :
196
+ return false;
197
+ }
198
+
199
+ return true;
200
+ }
201
+
202
+ static void fixed_mtrr_seg_unit_range (int seg , int unit , u64 * start , u64 * end )
203
+ {
204
+ struct fixed_mtrr_segment * mtrr_seg = & fixed_seg_table [seg ];
205
+ u64 unit_size = fixed_mtrr_seg_unit_size (seg );
206
+
207
+ * start = mtrr_seg -> start + unit * unit_size ;
208
+ * end = * start + unit_size ;
209
+ WARN_ON (* end > mtrr_seg -> end );
210
+ }
211
+
212
+ static int fixed_mtrr_seg_unit_range_index (int seg , int unit )
213
+ {
214
+ struct fixed_mtrr_segment * mtrr_seg = & fixed_seg_table [seg ];
215
+
216
+ WARN_ON (mtrr_seg -> start + unit * fixed_mtrr_seg_unit_size (seg )
217
+ > mtrr_seg -> end );
218
+
219
+ /* each unit has 8 ranges. */
220
+ return mtrr_seg -> range_start + 8 * unit ;
221
+ }
222
+
223
+ static bool fixed_msr_to_range (u32 msr , u64 * start , u64 * end )
224
+ {
225
+ int seg , unit ;
226
+
227
+ if (!fixed_msr_to_seg_unit (msr , & seg , & unit ))
228
+ return false;
229
+
230
+ fixed_mtrr_seg_unit_range (seg , unit , start , end );
231
+ return true;
232
+ }
233
+
234
+ static int fixed_msr_to_range_index (u32 msr )
235
+ {
236
+ int seg , unit ;
237
+
238
+ if (!fixed_msr_to_seg_unit (msr , & seg , & unit ))
239
+ return -1 ;
240
+
241
+ return fixed_mtrr_seg_unit_range_index (seg , unit );
242
+ }
243
+
123
244
static void update_mtrr (struct kvm_vcpu * vcpu , u32 msr )
124
245
{
125
246
struct kvm_mtrr * mtrr_state = & vcpu -> arch .mtrr_state ;
126
247
gfn_t start , end , mask ;
127
248
int index ;
128
- bool is_fixed = true;
129
249
130
250
if (msr == MSR_IA32_CR_PAT || !tdp_enabled ||
131
251
!kvm_arch_has_noncoherent_dma (vcpu -> kvm ))
@@ -134,32 +254,15 @@ static void update_mtrr(struct kvm_vcpu *vcpu, u32 msr)
134
254
if (!mtrr_is_enabled (mtrr_state ) && msr != MSR_MTRRdefType )
135
255
return ;
136
256
137
- switch (msr ) {
138
- case MSR_MTRRfix64K_00000 :
139
- start = 0x0 ;
140
- end = 0x80000 ;
141
- break ;
142
- case MSR_MTRRfix16K_80000 :
143
- start = 0x80000 ;
144
- end = 0xa0000 ;
145
- break ;
146
- case MSR_MTRRfix16K_A0000 :
147
- start = 0xa0000 ;
148
- end = 0xc0000 ;
149
- break ;
150
- case MSR_MTRRfix4K_C0000 ... MSR_MTRRfix4K_F8000 :
151
- index = msr - MSR_MTRRfix4K_C0000 ;
152
- start = 0xc0000 + index * (32 << 10 );
153
- end = start + (32 << 10 );
154
- break ;
155
- case MSR_MTRRdefType :
156
- is_fixed = false;
257
+ /* fixed MTRRs. */
258
+ if (fixed_msr_to_range (msr , & start , & end )) {
259
+ if (!fixed_mtrr_is_enabled (mtrr_state ))
260
+ return ;
261
+ } else if (msr == MSR_MTRRdefType ) {
157
262
start = 0x0 ;
158
263
end = ~0ULL ;
159
- break ;
160
- default :
264
+ } else {
161
265
/* variable range MTRRs. */
162
- is_fixed = false;
163
266
index = (msr - 0x200 ) / 2 ;
164
267
start = mtrr_state -> var_ranges [index ].base & PAGE_MASK ;
165
268
mask = mtrr_state -> var_ranges [index ].mask & PAGE_MASK ;
@@ -168,38 +271,32 @@ static void update_mtrr(struct kvm_vcpu *vcpu, u32 msr)
168
271
end = ((start & mask ) | ~mask ) + 1 ;
169
272
}
170
273
171
- if (is_fixed && !fixed_mtrr_is_enabled (mtrr_state ))
172
- return ;
173
-
174
274
kvm_zap_gfn_range (vcpu -> kvm , gpa_to_gfn (start ), gpa_to_gfn (end ));
175
275
}
176
276
177
277
int kvm_mtrr_set_msr (struct kvm_vcpu * vcpu , u32 msr , u64 data )
178
278
{
179
- u64 * p = ( u64 * ) & vcpu -> arch . mtrr_state . fixed_ranges ;
279
+ int index ;
180
280
181
281
if (!kvm_mtrr_valid (vcpu , msr , data ))
182
282
return 1 ;
183
283
184
- if (msr == MSR_MTRRdefType )
284
+ index = fixed_msr_to_range_index (msr );
285
+ if (index >= 0 )
286
+ * (u64 * )& vcpu -> arch .mtrr_state .fixed_ranges [index ] = data ;
287
+ else if (msr == MSR_MTRRdefType )
185
288
vcpu -> arch .mtrr_state .deftype = data ;
186
- else if (msr == MSR_MTRRfix64K_00000 )
187
- p [0 ] = data ;
188
- else if (msr == MSR_MTRRfix16K_80000 || msr == MSR_MTRRfix16K_A0000 )
189
- p [1 + msr - MSR_MTRRfix16K_80000 ] = data ;
190
- else if (msr >= MSR_MTRRfix4K_C0000 && msr <= MSR_MTRRfix4K_F8000 )
191
- p [3 + msr - MSR_MTRRfix4K_C0000 ] = data ;
192
289
else if (msr == MSR_IA32_CR_PAT )
193
290
vcpu -> arch .pat = data ;
194
291
else { /* Variable MTRRs */
195
- int idx , is_mtrr_mask ;
292
+ int is_mtrr_mask ;
196
293
197
- idx = (msr - 0x200 ) / 2 ;
198
- is_mtrr_mask = msr - 0x200 - 2 * idx ;
294
+ index = (msr - 0x200 ) / 2 ;
295
+ is_mtrr_mask = msr - 0x200 - 2 * index ;
199
296
if (!is_mtrr_mask )
200
- vcpu -> arch .mtrr_state .var_ranges [idx ].base = data ;
297
+ vcpu -> arch .mtrr_state .var_ranges [index ].base = data ;
201
298
else
202
- vcpu -> arch .mtrr_state .var_ranges [idx ].mask = data ;
299
+ vcpu -> arch .mtrr_state .var_ranges [index ].mask = data ;
203
300
}
204
301
205
302
update_mtrr (vcpu , msr );
@@ -208,7 +305,7 @@ int kvm_mtrr_set_msr(struct kvm_vcpu *vcpu, u32 msr, u64 data)
208
305
209
306
int kvm_mtrr_get_msr (struct kvm_vcpu * vcpu , u32 msr , u64 * pdata )
210
307
{
211
- u64 * p = ( u64 * ) & vcpu -> arch . mtrr_state . fixed_ranges ;
308
+ int index ;
212
309
213
310
/* MSR_MTRRcap is a readonly MSR. */
214
311
if (msr == MSR_MTRRcap ) {
@@ -225,25 +322,22 @@ int kvm_mtrr_get_msr(struct kvm_vcpu *vcpu, u32 msr, u64 *pdata)
225
322
if (!msr_mtrr_valid (msr ))
226
323
return 1 ;
227
324
228
- if (msr == MSR_MTRRdefType )
325
+ index = fixed_msr_to_range_index (msr );
326
+ if (index >= 0 )
327
+ * pdata = * (u64 * )& vcpu -> arch .mtrr_state .fixed_ranges [index ];
328
+ else if (msr == MSR_MTRRdefType )
229
329
* pdata = vcpu -> arch .mtrr_state .deftype ;
230
- else if (msr == MSR_MTRRfix64K_00000 )
231
- * pdata = p [0 ];
232
- else if (msr == MSR_MTRRfix16K_80000 || msr == MSR_MTRRfix16K_A0000 )
233
- * pdata = p [1 + msr - MSR_MTRRfix16K_80000 ];
234
- else if (msr >= MSR_MTRRfix4K_C0000 && msr <= MSR_MTRRfix4K_F8000 )
235
- * pdata = p [3 + msr - MSR_MTRRfix4K_C0000 ];
236
330
else if (msr == MSR_IA32_CR_PAT )
237
331
* pdata = vcpu -> arch .pat ;
238
332
else { /* Variable MTRRs */
239
- int idx , is_mtrr_mask ;
333
+ int is_mtrr_mask ;
240
334
241
- idx = (msr - 0x200 ) / 2 ;
242
- is_mtrr_mask = msr - 0x200 - 2 * idx ;
335
+ index = (msr - 0x200 ) / 2 ;
336
+ is_mtrr_mask = msr - 0x200 - 2 * index ;
243
337
if (!is_mtrr_mask )
244
- * pdata = vcpu -> arch .mtrr_state .var_ranges [idx ].base ;
338
+ * pdata = vcpu -> arch .mtrr_state .var_ranges [index ].base ;
245
339
else
246
- * pdata = vcpu -> arch .mtrr_state .var_ranges [idx ].mask ;
340
+ * pdata = vcpu -> arch .mtrr_state .var_ranges [index ].mask ;
247
341
}
248
342
249
343
return 0 ;
0 commit comments