diff options
author | Xiao Guangrong <guangrong.xiao@linux.intel.com> | 2015-06-15 04:55:31 -0400 |
---|---|---|
committer | Paolo Bonzini <pbonzini@redhat.com> | 2015-06-19 11:16:28 -0400 |
commit | 19efffa244071ccd0385b240d03adb38feaab04e (patch) | |
tree | d6fce4bc6222d5ae0be4d42099b516e9ce70a96e | |
parent | a13842dc668b40daef4327294a6d3bdc8bd30276 (diff) |
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 <guangrong.xiao@linux.intel.com>
[Fix list insertion sort, simplify var_mtrr_range_is_valid to just
test the V bit. - Paolo]
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
-rw-r--r-- | arch/x86/include/asm/kvm_host.h | 3 | ||||
-rw-r--r-- | arch/x86/kvm/mtrr.c | 50 | ||||
-rw-r--r-- | arch/x86/kvm/x86.c | 2 | ||||
-rw-r--r-- | arch/x86/kvm/x86.h | 1 |
4 files changed, 45 insertions, 11 deletions
diff --git a/arch/x86/include/asm/kvm_host.h b/arch/x86/include/asm/kvm_host.h index f73554874845..f2d60cce7595 100644 --- a/arch/x86/include/asm/kvm_host.h +++ b/arch/x86/include/asm/kvm_host.h | |||
@@ -345,12 +345,15 @@ enum { | |||
345 | struct kvm_mtrr_range { | 345 | struct kvm_mtrr_range { |
346 | u64 base; | 346 | u64 base; |
347 | u64 mask; | 347 | u64 mask; |
348 | struct list_head node; | ||
348 | }; | 349 | }; |
349 | 350 | ||
350 | struct kvm_mtrr { | 351 | struct kvm_mtrr { |
351 | struct kvm_mtrr_range var_ranges[KVM_NR_VAR_MTRR]; | 352 | struct kvm_mtrr_range var_ranges[KVM_NR_VAR_MTRR]; |
352 | mtrr_type fixed_ranges[KVM_NR_FIXED_MTRR_REGION]; | 353 | mtrr_type fixed_ranges[KVM_NR_FIXED_MTRR_REGION]; |
353 | u64 deftype; | 354 | u64 deftype; |
355 | |||
356 | struct list_head head; | ||
354 | }; | 357 | }; |
355 | 358 | ||
356 | struct kvm_vcpu_arch { | 359 | struct kvm_vcpu_arch { |
diff --git a/arch/x86/kvm/mtrr.c b/arch/x86/kvm/mtrr.c index b081e3ba186f..faa582488bb8 100644 --- a/arch/x86/kvm/mtrr.c +++ b/arch/x86/kvm/mtrr.c | |||
@@ -285,6 +285,39 @@ static void update_mtrr(struct kvm_vcpu *vcpu, u32 msr) | |||
285 | kvm_zap_gfn_range(vcpu->kvm, gpa_to_gfn(start), gpa_to_gfn(end)); | 285 | kvm_zap_gfn_range(vcpu->kvm, gpa_to_gfn(start), gpa_to_gfn(end)); |
286 | } | 286 | } |
287 | 287 | ||
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 | |||
288 | int kvm_mtrr_set_msr(struct kvm_vcpu *vcpu, u32 msr, u64 data) | 321 | int kvm_mtrr_set_msr(struct kvm_vcpu *vcpu, u32 msr, u64 data) |
289 | { | 322 | { |
290 | int index; | 323 | int index; |
@@ -299,16 +332,8 @@ int kvm_mtrr_set_msr(struct kvm_vcpu *vcpu, u32 msr, u64 data) | |||
299 | vcpu->arch.mtrr_state.deftype = data; | 332 | vcpu->arch.mtrr_state.deftype = data; |
300 | else if (msr == MSR_IA32_CR_PAT) | 333 | else if (msr == MSR_IA32_CR_PAT) |
301 | vcpu->arch.pat = data; | 334 | vcpu->arch.pat = data; |
302 | else { /* Variable MTRRs */ | 335 | else |
303 | int is_mtrr_mask; | 336 | set_var_mtrr_msr(vcpu, msr, data); |
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 | } | ||
312 | 337 | ||
313 | update_mtrr(vcpu, msr); | 338 | update_mtrr(vcpu, msr); |
314 | return 0; | 339 | return 0; |
@@ -354,6 +379,11 @@ int kvm_mtrr_get_msr(struct kvm_vcpu *vcpu, u32 msr, u64 *pdata) | |||
354 | return 0; | 379 | return 0; |
355 | } | 380 | } |
356 | 381 | ||
382 | void kvm_vcpu_mtrr_init(struct kvm_vcpu *vcpu) | ||
383 | { | ||
384 | INIT_LIST_HEAD(&vcpu->arch.mtrr_state.head); | ||
385 | } | ||
386 | |||
357 | u8 kvm_mtrr_get_guest_memory_type(struct kvm_vcpu *vcpu, gfn_t gfn) | 387 | u8 kvm_mtrr_get_guest_memory_type(struct kvm_vcpu *vcpu, gfn_t gfn) |
358 | { | 388 | { |
359 | struct kvm_mtrr *mtrr_state = &vcpu->arch.mtrr_state; | 389 | struct kvm_mtrr *mtrr_state = &vcpu->arch.mtrr_state; |
diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c index 2ffad7f2a28e..6574fa36cb65 100644 --- a/arch/x86/kvm/x86.c +++ b/arch/x86/kvm/x86.c | |||
@@ -7379,13 +7379,13 @@ int kvm_arch_vcpu_setup(struct kvm_vcpu *vcpu) | |||
7379 | { | 7379 | { |
7380 | int r; | 7380 | int r; |
7381 | 7381 | ||
7382 | kvm_vcpu_mtrr_init(vcpu); | ||
7382 | r = vcpu_load(vcpu); | 7383 | r = vcpu_load(vcpu); |
7383 | if (r) | 7384 | if (r) |
7384 | return r; | 7385 | return r; |
7385 | kvm_vcpu_reset(vcpu, false); | 7386 | kvm_vcpu_reset(vcpu, false); |
7386 | kvm_mmu_setup(vcpu); | 7387 | kvm_mmu_setup(vcpu); |
7387 | vcpu_put(vcpu); | 7388 | vcpu_put(vcpu); |
7388 | |||
7389 | return r; | 7389 | return r; |
7390 | } | 7390 | } |
7391 | 7391 | ||
diff --git a/arch/x86/kvm/x86.h b/arch/x86/kvm/x86.h index aeb0bb2f1df4..0e4727c49279 100644 --- a/arch/x86/kvm/x86.h +++ b/arch/x86/kvm/x86.h | |||
@@ -162,6 +162,7 @@ int kvm_write_guest_virt_system(struct x86_emulate_ctxt *ctxt, | |||
162 | gva_t addr, void *val, unsigned int bytes, | 162 | gva_t addr, void *val, unsigned int bytes, |
163 | struct x86_exception *exception); | 163 | struct x86_exception *exception); |
164 | 164 | ||
165 | void kvm_vcpu_mtrr_init(struct kvm_vcpu *vcpu); | ||
165 | u8 kvm_mtrr_get_guest_memory_type(struct kvm_vcpu *vcpu, gfn_t gfn); | 166 | u8 kvm_mtrr_get_guest_memory_type(struct kvm_vcpu *vcpu, gfn_t gfn); |
166 | bool kvm_mtrr_valid(struct kvm_vcpu *vcpu, u32 msr, u64 data); | 167 | bool kvm_mtrr_valid(struct kvm_vcpu *vcpu, u32 msr, u64 data); |
167 | int kvm_mtrr_set_msr(struct kvm_vcpu *vcpu, u32 msr, u64 data); | 168 | int kvm_mtrr_set_msr(struct kvm_vcpu *vcpu, u32 msr, u64 data); |