Skip to content

Commit de9aef5

Browse files
Xiao Guangrongbonzini
authored andcommitted
KVM: MTRR: introduce fixed_mtrr_segment table
This table summarizes the information of fixed MTRRs and introduce some APIs to abstract its operation which helps us to clean up the code and will be used in later patches Signed-off-by: Xiao Guangrong <[email protected]> [Change range_size to range_shift, in order to avoid udivdi3 errors. - Paolo] Signed-off-by: Paolo Bonzini <[email protected]>
1 parent 3f3f78b commit de9aef5

File tree

1 file changed

+147
-53
lines changed

1 file changed

+147
-53
lines changed

arch/x86/kvm/mtrr.c

Lines changed: 147 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -120,12 +120,132 @@ static u8 mtrr_default_type(struct kvm_mtrr *mtrr_state)
120120
return mtrr_state->deftype & IA32_MTRR_DEF_TYPE_TYPE_MASK;
121121
}
122122

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+
123244
static void update_mtrr(struct kvm_vcpu *vcpu, u32 msr)
124245
{
125246
struct kvm_mtrr *mtrr_state = &vcpu->arch.mtrr_state;
126247
gfn_t start, end, mask;
127248
int index;
128-
bool is_fixed = true;
129249

130250
if (msr == MSR_IA32_CR_PAT || !tdp_enabled ||
131251
!kvm_arch_has_noncoherent_dma(vcpu->kvm))
@@ -134,32 +254,15 @@ static void update_mtrr(struct kvm_vcpu *vcpu, u32 msr)
134254
if (!mtrr_is_enabled(mtrr_state) && msr != MSR_MTRRdefType)
135255
return;
136256

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) {
157262
start = 0x0;
158263
end = ~0ULL;
159-
break;
160-
default:
264+
} else {
161265
/* variable range MTRRs. */
162-
is_fixed = false;
163266
index = (msr - 0x200) / 2;
164267
start = mtrr_state->var_ranges[index].base & PAGE_MASK;
165268
mask = mtrr_state->var_ranges[index].mask & PAGE_MASK;
@@ -168,38 +271,32 @@ static void update_mtrr(struct kvm_vcpu *vcpu, u32 msr)
168271
end = ((start & mask) | ~mask) + 1;
169272
}
170273

171-
if (is_fixed && !fixed_mtrr_is_enabled(mtrr_state))
172-
return;
173-
174274
kvm_zap_gfn_range(vcpu->kvm, gpa_to_gfn(start), gpa_to_gfn(end));
175275
}
176276

177277
int kvm_mtrr_set_msr(struct kvm_vcpu *vcpu, u32 msr, u64 data)
178278
{
179-
u64 *p = (u64 *)&vcpu->arch.mtrr_state.fixed_ranges;
279+
int index;
180280

181281
if (!kvm_mtrr_valid(vcpu, msr, data))
182282
return 1;
183283

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)
185288
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;
192289
else if (msr == MSR_IA32_CR_PAT)
193290
vcpu->arch.pat = data;
194291
else { /* Variable MTRRs */
195-
int idx, is_mtrr_mask;
292+
int is_mtrr_mask;
196293

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;
199296
if (!is_mtrr_mask)
200-
vcpu->arch.mtrr_state.var_ranges[idx].base = data;
297+
vcpu->arch.mtrr_state.var_ranges[index].base = data;
201298
else
202-
vcpu->arch.mtrr_state.var_ranges[idx].mask = data;
299+
vcpu->arch.mtrr_state.var_ranges[index].mask = data;
203300
}
204301

205302
update_mtrr(vcpu, msr);
@@ -208,7 +305,7 @@ int kvm_mtrr_set_msr(struct kvm_vcpu *vcpu, u32 msr, u64 data)
208305

209306
int kvm_mtrr_get_msr(struct kvm_vcpu *vcpu, u32 msr, u64 *pdata)
210307
{
211-
u64 *p = (u64 *)&vcpu->arch.mtrr_state.fixed_ranges;
308+
int index;
212309

213310
/* MSR_MTRRcap is a readonly MSR. */
214311
if (msr == MSR_MTRRcap) {
@@ -225,25 +322,22 @@ int kvm_mtrr_get_msr(struct kvm_vcpu *vcpu, u32 msr, u64 *pdata)
225322
if (!msr_mtrr_valid(msr))
226323
return 1;
227324

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)
229329
*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];
236330
else if (msr == MSR_IA32_CR_PAT)
237331
*pdata = vcpu->arch.pat;
238332
else { /* Variable MTRRs */
239-
int idx, is_mtrr_mask;
333+
int is_mtrr_mask;
240334

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;
243337
if (!is_mtrr_mask)
244-
*pdata = vcpu->arch.mtrr_state.var_ranges[idx].base;
338+
*pdata = vcpu->arch.mtrr_state.var_ranges[index].base;
245339
else
246-
*pdata = vcpu->arch.mtrr_state.var_ranges[idx].mask;
340+
*pdata = vcpu->arch.mtrr_state.var_ranges[index].mask;
247341
}
248342

249343
return 0;

0 commit comments

Comments
 (0)