Skip to content

Commit 19efffa

Browse files
Xiao Guangrongbonzini
authored andcommitted
KVM: MTRR: sort variable MTRRs
Sort all valid variable MTRRs based on its base address, it will help us to check a range to see if it's fully contained in variable MTRRs Signed-off-by: Xiao Guangrong <[email protected]> [Fix list insertion sort, simplify var_mtrr_range_is_valid to just test the V bit. - Paolo] Signed-off-by: Paolo Bonzini <[email protected]>
1 parent a13842d commit 19efffa

File tree

4 files changed

+45
-11
lines changed

4 files changed

+45
-11
lines changed

arch/x86/include/asm/kvm_host.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -345,12 +345,15 @@ enum {
345345
struct kvm_mtrr_range {
346346
u64 base;
347347
u64 mask;
348+
struct list_head node;
348349
};
349350

350351
struct kvm_mtrr {
351352
struct kvm_mtrr_range var_ranges[KVM_NR_VAR_MTRR];
352353
mtrr_type fixed_ranges[KVM_NR_FIXED_MTRR_REGION];
353354
u64 deftype;
355+
356+
struct list_head head;
354357
};
355358

356359
struct kvm_vcpu_arch {

arch/x86/kvm/mtrr.c

Lines changed: 40 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -285,6 +285,39 @@ static void update_mtrr(struct kvm_vcpu *vcpu, u32 msr)
285285
kvm_zap_gfn_range(vcpu->kvm, gpa_to_gfn(start), gpa_to_gfn(end));
286286
}
287287

288+
static bool var_mtrr_range_is_valid(struct kvm_mtrr_range *range)
289+
{
290+
return (range->mask & (1 << 11)) != 0;
291+
}
292+
293+
static void set_var_mtrr_msr(struct kvm_vcpu *vcpu, u32 msr, u64 data)
294+
{
295+
struct kvm_mtrr *mtrr_state = &vcpu->arch.mtrr_state;
296+
struct kvm_mtrr_range *tmp, *cur;
297+
int index, is_mtrr_mask;
298+
299+
index = (msr - 0x200) / 2;
300+
is_mtrr_mask = msr - 0x200 - 2 * index;
301+
cur = &mtrr_state->var_ranges[index];
302+
303+
/* remove the entry if it's in the list. */
304+
if (var_mtrr_range_is_valid(cur))
305+
list_del(&mtrr_state->var_ranges[index].node);
306+
307+
if (!is_mtrr_mask)
308+
cur->base = data;
309+
else
310+
cur->mask = data;
311+
312+
/* add it to the list if it's enabled. */
313+
if (var_mtrr_range_is_valid(cur)) {
314+
list_for_each_entry(tmp, &mtrr_state->head, node)
315+
if (cur->base >= tmp->base)
316+
break;
317+
list_add_tail(&cur->node, &tmp->node);
318+
}
319+
}
320+
288321
int kvm_mtrr_set_msr(struct kvm_vcpu *vcpu, u32 msr, u64 data)
289322
{
290323
int index;
@@ -299,16 +332,8 @@ int kvm_mtrr_set_msr(struct kvm_vcpu *vcpu, u32 msr, u64 data)
299332
vcpu->arch.mtrr_state.deftype = data;
300333
else if (msr == MSR_IA32_CR_PAT)
301334
vcpu->arch.pat = data;
302-
else { /* Variable MTRRs */
303-
int is_mtrr_mask;
304-
305-
index = (msr - 0x200) / 2;
306-
is_mtrr_mask = msr - 0x200 - 2 * index;
307-
if (!is_mtrr_mask)
308-
vcpu->arch.mtrr_state.var_ranges[index].base = data;
309-
else
310-
vcpu->arch.mtrr_state.var_ranges[index].mask = data;
311-
}
335+
else
336+
set_var_mtrr_msr(vcpu, msr, data);
312337

313338
update_mtrr(vcpu, msr);
314339
return 0;
@@ -354,6 +379,11 @@ int kvm_mtrr_get_msr(struct kvm_vcpu *vcpu, u32 msr, u64 *pdata)
354379
return 0;
355380
}
356381

382+
void kvm_vcpu_mtrr_init(struct kvm_vcpu *vcpu)
383+
{
384+
INIT_LIST_HEAD(&vcpu->arch.mtrr_state.head);
385+
}
386+
357387
u8 kvm_mtrr_get_guest_memory_type(struct kvm_vcpu *vcpu, gfn_t gfn)
358388
{
359389
struct kvm_mtrr *mtrr_state = &vcpu->arch.mtrr_state;

arch/x86/kvm/x86.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7379,13 +7379,13 @@ int kvm_arch_vcpu_setup(struct kvm_vcpu *vcpu)
73797379
{
73807380
int r;
73817381

7382+
kvm_vcpu_mtrr_init(vcpu);
73827383
r = vcpu_load(vcpu);
73837384
if (r)
73847385
return r;
73857386
kvm_vcpu_reset(vcpu, false);
73867387
kvm_mmu_setup(vcpu);
73877388
vcpu_put(vcpu);
7388-
73897389
return r;
73907390
}
73917391

arch/x86/kvm/x86.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -162,6 +162,7 @@ int kvm_write_guest_virt_system(struct x86_emulate_ctxt *ctxt,
162162
gva_t addr, void *val, unsigned int bytes,
163163
struct x86_exception *exception);
164164

165+
void kvm_vcpu_mtrr_init(struct kvm_vcpu *vcpu);
165166
u8 kvm_mtrr_get_guest_memory_type(struct kvm_vcpu *vcpu, gfn_t gfn);
166167
bool kvm_mtrr_valid(struct kvm_vcpu *vcpu, u32 msr, u64 data);
167168
int kvm_mtrr_set_msr(struct kvm_vcpu *vcpu, u32 msr, u64 data);

0 commit comments

Comments
 (0)